2017-05-16 15 views
0

私は戻り値を決定するためにテンプレート型をとる関数を持っています。テンプレートの型がテンプレートクラスのインスタンス化であるかどうかをコンパイル時に伝える方法はありますか?テンプレートタイプがテンプレートクラスのインスタンスであるかどうかを確認するには?

Ex。

class First { /* ... */ }; 

template <typename T> 
class Second { /* ... */ }; 

using MyType = boost::variant<First, Second<int>, Second<float>>; 

template <typename SecondType> 
auto func() -> MyType { 
    static_assert(/* what goes here?? */, "func() expects Second type"); 
    SecondType obj; 
    // ... 
    return obj; 
} 

MyType obj = func<Second<int>>(); 

私は型がテンプレートクラスのインスタンス化であるかどうかをテストする方法があるかどうか、私は一般的にはちょうど好奇心が強い

template <typename T> 
auto func() -> MyType { 
    static_assert(std::is_same<T, int>::value || std::is_same<T, float>::value, 
        "func template must be type int or float"); 

    Second<T> obj; 
    // ... 
    return obj; 
} 

MyType obj = func<int>(); 

を行うことによってこの問題を回避することが可能である知っていますか? MyTypeに6 Secondのインスタンスがあると、すべての可能なタイプをテストする必要はありません。ここで

+0

あなたは 'Second'を変更できますか? 'std :: true_type isSecond'メンバを追加できれば簡単です – Caleth

+0

可能なdupe [型がテンプレートであるかどうかをチェックするためにC++型の特性を使う方法はありますか?](http://stackoverflow.com/questions/13919234/is-there-a-way-c-type-traits-to-a-a-type-if-a-template-and-any-pr)は何ですか? – George

答えて

3

はオプションです:

#include <iostream> 
#include <type_traits> 
#include <string> 

template <class, template <class> class> 
struct is_instance : public std::false_type {}; 

template <class T, template <class> class U> 
struct is_instance<U<T>, U> : public std::true_type {}; 

template <class> 
class Second 
{}; 

int main() 
{ 
    using A = Second<int>; 
    using B = Second<std::string>; 
    using C = float; 
    std::cout << is_instance<A, Second>{} << '\n'; // prints 1 
    std::cout << is_instance<B, Second>{} << '\n'; // prints 1 
    std::cout << is_instance<C, Second>{} << '\n'; // prints 0 
} 

それは基本的には、テンプレートのインスタンス化されているタイプのためis_instance構造体を特化しています。

+1

これを 'template class> struct is_instance'にしてください。この方法では、1つのパラメータだけを持つテンプレートに限定されません。また、これはtypename引数を持つテンプレートに対してのみ機能することに注意してください。 –

1

別のオプションは、アンリさんのコメントに拾っ:

#include <iostream> 
#include <type_traits> 
#include <string> 

template <class, template <class, class...> class> 
struct is_instance : public std::false_type {}; 

template <class...Ts, template <class, class...> class U> 
struct is_instance<U<Ts...>, U> : public std::true_type {}; 

template <class> 
class Second 
{}; 

template <class, class, class> 
class Third 
{}; 

int main() 
{ 
    using A = Second<int>; 
    using B = Second<std::string>; 
    using C = float; 
    using D = Third<std::string, int, void>; 
    std::cout << is_instance<A, Second>{} << '\n'; // prints 1 
    std::cout << is_instance<B, Second>{} << '\n'; // prints 1 
    std::cout << is_instance<C, Second>{} << '\n'; // prints 0 
    std::cout << is_instance<D, Third>{} << '\n'; // prints 1 
} 
関連する問題