如何确定模板参数是否为std::complex?

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

2
模板特化 - Danh
4
你想要“专攻”什么?请给出一个具体的例子,目前的帖子信息不足以直接回答。 - Holt
4个回答

15

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

首先,您需要定义一个默认为 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; }

编辑:此实用程序函数在 C++14 及以上版本中不需要或有用,因为 std::integral_type 实现了 operator()。

用法:

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

4
你可以采用标签派发技术来实现你的解决方案。
以下是一个最小化、可工作的示例:
#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
我理解您的问题是希望实现一种通用方法来测试给定类型是否为给定模板模板类型的特化。可以使用类模板进行操作,就像在Frank的回答中所示。我将向您展示一种补充专业化的方法 - 使用函数重载的模板类型别名:
#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, "!");
}

【演示】

您可以按照以下方式使用trait:

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


1
这个也可以: 实时演示
#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库。被接受的答案对我有用。 - Soo
是的,那是我的猜测。然而我是通过谷歌搜索到这里的,并不喜欢任何答案。我需要一个更短的答案 :) 这个答案对我来说已经足够短,可以在 enable_if 结构中使用。其他能够使用 boost 的人也可能会喜欢它 :) - Janek_Kozicki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接