Специализация шаблона только для базового POD - PullRequest
6 голосов
/ 14 января 2012

Есть ли тонкий прием для специализации шаблона, чтобы я мог применить одну специализацию к basic POD (когда я говорю базовый POD, я не особенно хочу struct POD (но я возьму это)).

template<typename T>
struct DoStuff
{
    void operator()() { std::cout << "Generic\n";}
};
template<>
struct DoStuff</*SOme Magic*/>
{
    void operator()() { std::cout << "POD Type\n";}
};

Или мне нужно написать специализации для каждого из встроенных типов?

template<typename T>
struct DoStuff
{
    void operator()() { std::cout << "Generic\n";}
};


// Repeat the following template for each of
// unsigned long long, unsigned long, unsigned int, unsigned short, unsigned char
//          long long,          long,          int,          short, signed   char
// long double, double, float, bool
// Did I forget anything?
//
// Is char covered by unsigned/signed char or do I need a specialization for that?
template<>  
struct DoStuff<int>
{
    void operator()() { std::cout << "POD Type\n";}
};

Unit Test.

int main()
{
    DoStuff<int>           intStuff;
    intStuff();            // Print POD Type


    DoStuff<std::string>   strStuff;
    strStuff();            // Print Generic
}

Ответы [ 3 ]

6 голосов
/ 14 января 2012

Если вы действительно хотите использовать только базовые типы, а не определяемые пользователем типы POD, то должно работать следующее:

#include <iostream>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/type_traits/is_same.hpp>

template<typename T>
struct non_void_fundamental : boost::integral_constant<
    bool,
    boost::is_fundamental<T>::value && !boost::is_same<T, void>::value
>
{ };

template<typename T, bool Enable = non_void_fundamental<T>::value>
struct DoStuff
{
    void operator ()() { std::cout << "Generic\n"; } const
};

template<>
struct DoStuff<T, true>
{
    void operator ()() { std::cout << "POD Type\n"; } const
};

Если вам также нужны определяемые пользователем типы POD, используйте boost::is_pod<> вместо non_void_fundamental<> (а если вы используете C ++ 11 и делаете это в целях оптимизации, используйте std::is_trivially_copyable<>).

6 голосов
/ 14 января 2012

В C ++ 11 многие черты были добавлены в стандартную библиотеку, и большинство, кажется, особенно нацелено на интересные специализации (и особенно побитовые манипуляции).

Черта верхнего уровня, которая вас может заинтересовать: std::is_trivial, однако есть много других:

  • std::is_trivially_default_constructible
  • std::is_trivially_copy_constructible
  • std::is_trivially_move_constructible
  • std::is_trivially_copyable (можно скопировать с помощью memcpy)

В общем, Стандарт пытался получить как можно более мелкие детали, поэтому вам не нужно полагаться на такие широкие допущения, как is_pod, а вместо этого точно настроить свои ограничения, чтобы они соответствовали тем, что действительно нужны вашим методам.

1 голос
/ 14 января 2012

Повышение имеет boost::is_pod. Это то, что вы ищете?

(Я никогда не использовал его, поэтому я не буду смущать себя, пытаясь сформулировать точный код, который вам требуется для вашего примера.)

...