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

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

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

[живое демо]

3

Другие решения

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

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

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

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

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

#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
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector