With this code you will have problems. If you need to distinguish between different types of characteristics, you need to do this at compile time, and not at run time. Depending on what operations you perform, one of the two branches of your if may not compile. Therefore, it is better to switch to a specialized function:
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*/); }
With this implementation technique, you only need to compile the branch you are using (i.e., be correct).
Edit:
Here are some additional information. The solution to this problem is the installation of patterns. I switch from is_fundamental to is_array to show how operations can work.
Let's start with the first example:
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); }
It will compile and run, and the compiler will see that only one branch of the if statement will be used and will delete the other as unused code.
In my second example, I will do someithing in the case when I use an array operation:
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); }
Now it will not compile. The reason is that int as an argument to the template t[0] poorly formed. You cannot use this run statement to distinguish between compile-time type properties that are needed in your code (in this example, the beeing array property and the use of t[0] ).
In the third example, we disable compile time by overloading functions:
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); }
Here is_array<T>::type is either true_type or false_type . This result is used as a selector to select the correct fun_impl overload at compile time, and only the selected overload is started and compiled.
Normal methods of this kind are used to select at compile time the best implementation that can only be compiled if the types have certain properties.
2nd edit:
This, of course, will change if static if is part of the language.