2013-05-29 4 views
5

В функции внутри класса шаблона я пытаюсь различать примитивные типы и другие.C++: альтернатива «std :: is_fundamental»?

В C++ 11 вы можете сделать:

if(std::is_fundamental<T>::value) 
{ 
    // Treat it as a primitive 
} 
else 
{ 
    //Treat it otherwise 
} 

Пожалуйста, поправьте меня, если я ошибаюсь, и это не только в C++ 11.

Есть ли альтернатива этому в более ранних версиях C++ ?

ответ

8

Вы можете использовать Boost's type traits в C++ 03, как это:

#include <boost/type_traits/is_fundamental.hpp> 

... 

if(boost::is_fundamental<T>::value) 
{ 
    // Treat it as a primitive 
} 
else 
{ 
    //Treat it otherwise 
} 

Я думаю, что это должно работать на C++ 98, а также.

+0

Спасибо. +1 для 'include'. – Subway

2

С помощью этого кода у вас наверняка возникнут проблемы. Если вам нужно различать разные типы признаков, это нужно делать во время компиляции, а не во время выполнения. В зависимости от того, какие операции вы выполняете, одна из двух ветвей вашего if не может компилироваться. Так что лучше направить на специализированную функцию:

void operation_impl(boost::true_type /*other params*/) { 
    // Treat it is primitive 
} 

void operation_impl(boost::false_type /*other params*/) { 
    // Treat it otherwise 
} 

template<class T> 
void operation(/* params*/) { 
    operation_impl(boost::is_fundamental<T>::type() /*other params*/); 
} 

С помощью этого метода реализации только используются отрасль должна составить (т.е. быть правильным).

Edit:

Вот некоторые дополнительные сведения. Решение этой проблемы связано с установлением шаблонов. Я переключаюсь с is_fundamental на is_array, чтобы показать, как операции могут завершиться неудачно.

Начнет с первым примером:

template <class T> 
void fun(T t) { 
    if(boost::is_array<T>::value) 
    { 
     std::cout << "true" << std::endl; 
    } 
    else 
    { 
     std::cout << "false" << std::endl; 
    } 
} 

void f(int i) { 
    fun(i); 
} 

Он будет скомпилировать и запустить, и компилятор будет видеть, что только одна ветви, если заявление будет использоваться и удалит другие как неиспользуемый код.

В моем втором примере я буду делать someithing в случае я использую операцию массива:

template<class T> 
void fun(T& t) { 
    if(boost::is_array<T>::value) 
    { 
     std::cout << t[0]; 
    } 
    else 
    { 
     std::cout << t; 
    } 
} 

void f(int i) { 
    fun(i); 
} 

Теперь он не будет компилироваться. Причина в том, что int в качестве аргумента шаблона t[0] плохо сформирован. Вы не можете использовать этот оператор выполнения, чтобы различать свойства типа во время компиляции, которые необходимы в вашем коде (в этом примере свойство beeing массива и использование t[0]).

В третьем примере мы disitinguish на время компиляции с помощью функции перегрузки:

template<class T> 
void fun_impl(boost::true_type, T& t) { 
    std::cout << t[0]; 
} 

template<class T> 
void fun_impl(boost::false_type, T& t) { 
    std::cout << t; 
} 

template<class T> 
void fun(T& t) { 
    fun_impl(typename boost::is_array<T>::type(),t); 
} 

void f(int i) { 
    fun(i); 
} 

Здесь is_array<T>::type либо true_type или false_type. Этот результат используется как селектор для выбора правильной перегрузки fun_impl во время компиляции, и только выбранная перегрузка запускается и компилируется.

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

второй править:

Это будет изменения курса, если static if является частью языка.

+0

не могли бы вы рассказать о проблеме, с которой я мог бы столкнуться с другим подходом? Или вы можете добавить ссылку на объяснение? Я не понял, что вы написали. – Subway

+0

Спасибо! +1 для разработки. У меня все еще есть вопрос: как я понимаю, ваша задача - собрать код и в дополнение сохранить компиляцию ненужного кода. Учитывая, что мой код компилируется, существуют ли реальные проблемы (например, неожиданное поведение), которые я могу встретить во время выполнения с использованием первого подхода? – Subway

+0

@Subway no Я думаю, что компилятор видит ваш boost :: is_fundamental :: значение как константа и удалит неиспользуемый код, поэтому нет накладных расходов во время выполнения и нет UB. Подход заключается в том, чтобы скомпилировать его. Элемент const value используется для использования с std :: enable_if (как интегральный шаблонный аргумент) и, конечно, для демонстрации (например, для печати значения). Я думаю, что для любой другой цели вы должны совершить тур через функцию перегрузки. –

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