質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

メタプログラミング

メタプログラミングとは、プログラミング技法の一つ。プログラムをプログラミングすることを指します。他のプログラムや、そのプログラム自体を操作・出力するメタプログラムを記述する作業をメタプログラミングと呼びます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2995閲覧

メタ関数と部分特殊化を同時に使いたい

s8079

総合スコア36

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

メタプログラミング

メタプログラミングとは、プログラミング技法の一つ。プログラムをプログラミングすることを指します。他のプログラムや、そのプログラム自体を操作・出力するメタプログラムを記述する作業をメタプログラミングと呼びます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/01/31 15:11

編集2020/02/01 07:21

前提・実現したいこと

テンプレートの型を整数型に限定したクラスを作り,それを部分特殊化をしたいです.
メタ関数を使うのは初めてですので,使い方を間違っているかもしれません.
よろしくお願いします.

発生している問題・エラーメッセージ

error C2754: 'Hoge<T*,nullptr>': 部分的特殊化は、依存非型テンプレート パラメーターを含むことができません。

該当のソースコード

C++

1#include <utility> 2template<typename T, typename std::enable_if<std::is_integral<T>::value, std::nullptr_t>::type = nullptr> 3class Hoge { 4 // 省略 5}; 6template<typename T> 7class Hoge<T*> { 8 // 省略 9}; 10int main() { 11 // 省略 12 return 0; 13}

補足情報(FW/ツールのバージョンなど)

C++11

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

cpp

1template<typename T> 2class Hoge<T*> { 3 // 省略 4};

cpp

1template<typename T> 2class Hoge<T*, nullptr> { 3 // 省略 4};

に書き換えることで一応動きますがここで注意があります。

この書き方の場合、std::enable_ifによる制約は特殊化されたほうにも働きます

このため、上記の書き換え後の場合次のようなエラーが出るでしょう。

prog.cc:7:17: error: non-type template argument specializes a template parameter with dependent type 'typename std::enable_if<std::is_integral<T>::value, std::nullptr_t>::type' struct Hoge<T*, nullptr> { ^ prog.cc:2:96: note: template parameter is declared here template<typename T, typename std::enable_if<std::is_integral<T>::value, std::nullptr_t>::type = nullptr> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ prog.cc:2:46: error: failed requirement 'std::is_integral<int *>::value'; 'enable_if' cannot be used to disable this declaration template<typename T, typename std::enable_if<std::is_integral<T>::value, std::nullptr_t>::type = nullptr> ^~~~~~~~~~~~~~~~~~~~~~~~~~ prog.cc:11:39: note: while substituting prior template arguments into non-type template parameter [with T = int *] static_assert(std::is_same_v<typename Hoge<int*>::type, int>); ^~~~~~~~~~ prog.cc:11:48: note: while checking a default template argument used here static_assert(std::is_same_v<typename Hoge<int*>::type, int>); ~~~~~~~~~^ prog.cc:11:51: error: expected a qualified name after 'typename' static_assert(std::is_same_v<typename Hoge<int*>::type, int>); ^ prog.cc:11:51: error: unknown type name 'type' 4 errors generated.

https://wandbox.org/permlink/fOcgDM7bOiQlRgJR

今回やりたかったのはおそらく整数型へのポインタ型の場合の処理を書きたかったのだと思いますが、それならばChironianさんの書いたような書き方が必要になります。

投稿2020/01/31 15:43

編集2020/01/31 16:12
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2020/01/31 16:10

おおっ、gccは通りますね。 でも、clangは通らないようです。 https://wandbox.org/permlink/p2fenhwHGxnjLeeR しかし、プライマリー・テンプレートのenable_ifが成立しない時、その非型パラメータの型はどうなるのでしょう? 関数テンプレートのようにあっさり候補から外れるってわけには行かない筈だから、わからんです。 ところで、実体化できます? 出来る気がしないです。
yumetodo

2020/01/31 16:17 編集

追記しました。制約の働く範囲の問題ですね。全体に掛けていい制約なら私が最初に示したやり方でいけます。 ちなみにこのnullptrとかいちゃうのは主にこういう制約のあるクラステンプレートを前方宣言するときに便利です。
Chironian

2020/01/31 16:20

あ~、なるほど。 部分特殊化というよりは、どちらかというと型を制限する時に使える方法なのですね。 (だって、プライマリー・テンプレートに合致しない型を指定したら、必ずエラーになる筈ですから、一部の型について別定義することはできない筈。)
guest

0

ベストアンサー

こんにちは。

それは関数テンプレートで部分特殊化的なことを行う時に良く見かける記法のようです。
クラス・テンプレートを定義部分特殊化する時には使えないと思います。

クラス・テンプレートを部分特殊化する時は、必ずプライマリーテンプレートを定義します。その際に最後のテンプレート引数のデフォルト値をvoidにして書くことが多いようです。
そして、部分特殊化テンプレートで、そのデフォルト値を指定したテンプレート・パラメータがvoidになるか、無定義になるように指定します。

C++

1#include <iostream> 2#include "typename.h" 3 4#include <utility> 5template<typename T, class tEnable=void> 6class Hoge 7{ 8public: 9 Hoge() { std::cout << "[0] T=" << TYPENAME(T) << "\n"; } 10}; 11template<typename T> 12class Hoge<T, typename std::enable_if<std::is_integral<T>::value>::type> 13{ 14public: 15 Hoge() { std::cout << "[1] T=" << TYPENAME(T) << "\n"; } 16}; 17template<typename T> 18class Hoge<T*> 19{ 20public: 21 Hoge() { std::cout << "[2] T*=" << TYPENAME(T*) << "\n"; } 22}; 23 24int main() 25{ 26 Hoge<double> hoge_double; 27 Hoge<int> hoge_int; 28 Hoge<int*> hoge_intPtr; 29 return 0; 30}

wandbox

投稿2020/01/31 15:41

編集2020/01/31 16:27
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2020/01/31 15:59 編集

そんな面倒なことしなくても行け~~ますよ~る場合もありますよ(私の回答参照
s8079

2020/02/01 03:24

あまり普通の使い方ではないかもしれませんが,yumetodoさんのように指定の型以外をエラーにすることは可能でしょうか. gccしかコンパイルが通らないのはあまり好ましくありません.
Chironian

2020/02/01 05:09

s8079さん 単純に下記定義を削除するだけでよいようですよ。 template<typename T> class Hoge<T*> { // 省略 }; https://wandbox.org/permlink/HtwMkNh3SzomMYW9 実体化で型を指定した時、その型がenable_if<>の条件に合致しなければ該当のテンプレートが定義されないのでエラーになります。エラー・メッセージは解読困難なので頭痛いですが、それはConceptを待つしか無いと思います。(https://cpprefjp.github.io/lang/cpp20/concepts.html) ですので、私は見たことはないですが単に私が知らないだけで、これは正当な使い方だろうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問