Search code examples
c++c++11templatestypecheckingcomplextype

How to identifying whether a template argument is std::complex?


How to identify whether a template parameter is std::complex? I want a general method which supports all data types like float, double, int, etc. I know that using std::is_same I can check specifically for a given type, for example, std::complex<float>. But here I require a general method.


Solution

  • As I understand your question you are looking for implementation of a general method to test if a given type is specialization of given template template type. This can be done using class template somewhat like in Frank's answer. I will present you complementary approach to specialization - template type alias with function overloading:

    #include <type_traits>
    #include <complex>
    #include <iostream>
    
    template <template <class...> class TT, class... Args>
    std::true_type is_tt_impl(TT<Args...>);
    template <template <class...> class TT>
    std::false_type is_tt_impl(...);
    
    template <template <class...> class TT, class T>
    using is_tt = decltype(is_tt_impl<TT>(std::declval<typename std::decay<T>::type>()));
    
    int main() {
        static_assert(is_tt<std::complex, std::complex<int>>::value, "!");
        static_assert(is_tt<std::complex, std::complex<float>>::value, "!");
        static_assert(!is_tt<std::complex, float>::value, "!");
    }
    

    [live demo]

    You can utilize the trait as follows:

    #include <type_traits>
    #include <complex>
    #include <iostream>
    
    //complementary approach to specialization one would be to use function overloading
    template <template <class...> class TT, class... Args>
    std::true_type is_tt_impl(TT<Args...>);
    template <template <class...> class TT>
    std::false_type is_tt_impl(...);
    
    template <template <class...> class TT, class T>
    using is_tt = decltype(is_tt_impl<TT>(std::declval<typename std::decay<T>::type>()));
    
    template <class T>
    typename std::enable_if<is_tt<std::complex, T>::value>::type print(T t) {
        std::cout << "(" << t.real() << "," << t.imag() << ")" << std::endl;
    }
    
    template <class T>
    typename std::enable_if<!is_tt<std::complex, T>::value>::type print(T t) {
        std::cout << t << std::endl;
    }
    
    
    int main() {
        print(std::complex<int>(1, 2));
        print(std::complex<double>(1.5, 2.5));
        print(5.5);
    }
    

    (1,2)
    (1.5,2.5)
    5.5

    [live demo]