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

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

新規登録して質問してみよう
ただいま回答率
85.35%
メタプログラミング

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

C++

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

Q&A

解決済

1回答

1247閲覧

インスタンスかどうかを区別するクラスの非型バージョンを作りたい

fluid_love

総合スコア21

メタプログラミング

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

C++

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

0グッド

0クリップ

投稿2021/05/02 07:34

前提

インスタンスであるかどうかを判定するクラスがあります(参考).

cpp

1 2template<typename T, template <typename ...> typename U> 3class is_instance_of { 4private: 5 template<typename V> class helper : public std::false_type {}; 6 template<typename... V> class helper<U<V...>> : public std::true_type {}; 7public: 8 static constexpr bool value = helper<T>::value; 9}; 10

これを用いると

cpp

1#include <iostream> 2#include <type_traits> 3 4template<typename... T> 5class A {}; 6 7int main(){ 8 9 using Ty1 = A<int, int, int>; 10 using Ty2 = int; 11 12 if constexpr (is_instance_of<Ty1,A>::value) {//true 13 std::cout << "Ty1: instance"; 14 } 15 if constexpr (is_instance_of<Ty2,A>::value) {//false 16 std::cout << "Ty2: instance"; 17 } 18 19} 20 21

出力結果↓

Ty1: instance

このような感じにインスタンスかどうかを区別できます.

質問

非型の場合にも同様に区別することは可能でしょうか

理想↓

cpp

1 2 3template<auto...> 4struct A {}; 5 6 7int main(){ 8 9 static_assert(is_instance_of_nontype<A<10> , A>);//ok 10 11 static_assert(is_instance_of_nontype<A<10.0f>, A>);//ok 12 13 static_assert(is_instance_of_nontype<int , A>);//error 14 15 static_assert(is_instance_of_nontype<A<'a'> , A>);//ok 16 17} 18

試したこと

C++17以前に同様の質問があり,型を指定すれば可能とのことでした.

C++17 C++20と進化し続けていますが,まだ上記のようにis_instance_of<A<10>,A>のように,型に指定せずに書くことは不可能なのでしょうか?

↓型を指定する必要がある

cpp

1 2template<typename X, typename T, template <X ...> typename U> 3class is_instance_of_nontype { 4private: 5 template<typename V> class helper : public std::false_type {}; 6 template<X... V> class helper<U<V...>> : public std::true_type {}; 7public: 8 static constexpr bool value = helper<T>::value; 9}; 10 11 12template<auto...> 13struct A {}; 14 15 16int main(){ 17 18 19 using T1 = A<10>; 20 using T2 = A<20>; 21 using T3 = A<10.0>; 22 using T4 = A<'a'>; 23 24 //true 25 if constexpr (is_instance_of_nontype<int, T1, A>::value) { 26 cout << "T1" << endl; 27 } 28 29 //false T2はA<int型>であってA<float型>でないのでfalse 30 if constexpr (is_instance_of_nontype<float, T2, A>::value) { 31 cout << "T2" << endl; 32 } 33 34 //true 35 if constexpr (is_instance_of_nontype<double, T3, A>::value) { 36 cout << "T3" << endl; 37 } 38 39 //true 40 if constexpr (is_instance_of_nontype<char, T4, A>::value) { 41 cout << "T4" << endl; 42 } 43 44 //理想は↓ 型にとらわれたくない 45 //if constexpr (is_instance_of_nontype<T2, A>::value) { //true 46 // 47 //} 48 49} 50

↓出力結果

T1 T3 T4

よろしくお願いします.

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

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

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

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

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

guest

回答1

0

ベストアンサー

このような定義で出来るはずです。

cpp

1#include <type_traits> 2 3template<class T, template <auto...> typename U> 4class is_instance_of_nontype { 5private: 6 template<class V> class helper : public std::false_type {}; 7 template<auto... V> class helper<U<V...>> : public std::true_type {}; 8public: 9 static constexpr bool value = helper<T>::value; 10};

C++17 までは非型テンプレート変数に渡せる値の型は整数、ポインタ、参照などに限られており、クラス型の値は渡せません。 C++20 以降はこの仕様は大幅に緩和されて double を含む算術型も渡せることになっているのですが、 clang の最新版でもまだ A<10.0> をエラーにするようです。 (gcc では OK)

投稿2021/05/02 08:30

SaitoAtsushi

総合スコア5684

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

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

fluid_love

2021/05/02 09:18

ありがとうございます!. 無事にできました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問