Как определить, является ли аргумент шаблона std::complex?

Как определить, является ли параметр шаблона std::complex? Мне нужен общий метод, который поддерживает все типы данных, такие как float, double, int и т. д. Я знаю, что с помощью std::is_same я могу проверить конкретный тип, например, std::complex<float>. Но здесь мне нужен общий метод.


person Soo    schedule 03.01.2017    source источник
comment
Специализация шаблона   -  person Danh    schedule 03.01.2017
comment
На чем вы хотите специализироваться? Добавьте конкретный пример, в вашем посте недостаточно информации, чтобы ответить как есть.   -  person Holt    schedule 03.01.2017


Ответы (4)


Насколько я понимаю ваш вопрос, вы ищете реализацию общего метода для проверки, является ли данный тип специализацией данного типа шаблона шаблона. Это можно сделать с помощью шаблона класса, как в ответе Фрэнка. Я представлю вам дополнительный подход к специализации - псевдоним типа шаблона с перегрузкой функций:

#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, "!");
}

[демонстрация]

Вы можете использовать черту следующим образом:

#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

[демонстрация]

person W.F.    schedule 03.01.2017

Это можно сделать с помощью частичной специализации шаблона.

Сначала вы определяете универсальный шаблон, который по умолчанию имеет значение 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; }

Редактировать: эта служебная функция не нужна или полезна с С++ 14 и выше, поскольку std::integral_type реализует оператор().

Использование:

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

Вы можете основывать свое решение на методе диспетчеризации тегов.
Ниже приведен минимальный рабочий пример:

#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, который принимает почти все и отправляет внутренне в нужную функцию.

person skypjack    schedule 03.01.2017

Это тоже работает: Живое демо

#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";
}
person cosurgi    schedule 01.05.2020
comment
Спасибо. Но я не смогу использовать библиотеку Boost. Принятый ответ сработал для меня. - person Soo; 02.05.2020
comment
Да, это было мое предположение. Однако я попал сюда через Google, и мне не понравился ни один из ответов. Мне нужен был более короткий :) Этот достаточно короткий, чтобы я мог использовать его в enable_if конструкциях. Другим, кто может использовать boost, это тоже может понравиться :) - person cosurgi; 02.05.2020