2017-01-03 2 views
3

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

+2

шаблона Специализация – Danh

+4

Что вы хотите "специализироваться"? Добавьте конкретный пример, на ваш пост нет достаточной информации, чтобы ответить, как есть. – Holt

ответ

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]

8

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

Сначала нужно определить кетчуп все шаблон, который по умолчанию неверно:

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

Смежные вопросы