【问题标题】:How to identifying whether a template argument is std::complex?如何识别模板参数是否为 std::complex?
【发布时间】:2017-01-03 07:30:48
【问题描述】:

如何判断模板参数是否为std::complex?我想要一个支持所有数据类型的通用方法,如 float、double、int 等。 我知道使用 std::is_same 我可以专门检查给定类型,例如std::complex<float>。 但是这里我需要一个通用的方法。

【问题讨论】:

  • 模板专业化
  • 你想“专攻”什么?添加一个具体的例子,您的帖子中没有足够的信息来回答。

标签: c++ c++11 templates typechecking complextype


【解决方案1】:

这可以使用部分模板特化来完成。

首先定义一个默认为 false 的包罗万象的模板:

template<typename T>
struct is_complex_t : public std::false_type {};

然后你为符合你的条件的类型提供一个重载:

template<typename T>
struct is_complex_t<std::complex<T>> : public std::true_type {};

我还想添加一个实用函数:

template<typename T>
constexpr bool is_complex() { return is_complex_t<T>::value; }

编辑:由于 std::integral_type 实现了 operator(),因此 c++14 及更高版本不需要此实用程序函数。

用法:

bool int_is_complex = is_complex<int>(); //false
bool complex_is_complex = is_complex<std::complex<float>>(); //true

【讨论】:

    【解决方案2】:

    据我了解,您正在寻找一种通用方法的实现来测试给定类型是否是给定模板模板类型的特化。这可以使用类似于Frank's answer 的类模板来完成。我将向您介绍专门化的补充方法 - 具有函数重载的模板类型别名:

    #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]

    您可以按如下方式利用该特征:

    #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]

    【讨论】:

      【解决方案3】:

      您可以将解决方案基于标签调度技术。
      下面是一个最小的工作示例:

      #include<complex>
      #include<utility>
      #include<iostream>
      
      class C {
          template<typename T>
          void f(int, std::complex<T>) {
              std::cout << "complex" << std::endl;
          }
      
          template<typename T>
          void f(char, T &&t) {
              std::cout << "something else" << std::endl;
          }
      
      public:
          template<typename T>
          void f(T &&t) {
              f(0, std::forward<T>(t));
          }
      };
      
      int main() {
          C c;
          c.f(0);
          c.f(std::complex<float>{});
      }
      

      这为您提供了一个通用方法 f,它几乎可以接受任何内容并在内部分派给正确的函数。

      【讨论】:

        【解决方案4】:

        这个也可以:Live Demo

        #include <boost/type_traits/is_complex.hpp>
        #include <iostream>
        #include <complex>
        int main() {
            std::cout << std::boolalpha;
            std::cout << boost::is_complex<std::complex<float>>::value << "\n";
            std::cout << boost::is_complex<long double>::value << "\n";
        }
        

        【讨论】:

        • 谢谢。但我可能无法使用 Boost 库。接受的答案对我有用。
        • 是的,这是我的猜测。但是我通过谷歌来到这里,并且不喜欢任何答案。我需要一个更短的 :) 这个足够短,我可以在 enable_if 结构中使用。其他可以使用 boost 的人可能也会喜欢它:)
        猜你喜欢
        • 1970-01-01
        • 2019-03-22
        • 2017-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-07
        • 2014-01-03
        • 1970-01-01
        相关资源
        最近更新 更多