I was watching the latest C9 lecture and noticed something interesting..
In his introduction to type_traits, Stephan uses the following (as he says, contrived) example:
template <typename T>
void foo(T t, true_type)
{
std::cout << t << " is integral";
}
template <typename T>
void foo(T t, false_type)
{
std::cout << t << " is not integral";
}
template <typename T>
void bar(T t)
{
foo(t, typename is_integral<T>::type()
);
}
This seems to be far more complicated than:
template <typename T>
void foo(T t)
{
if(std::is_integral<T>::value
)
std::cout << "integral";
else
std::cout << "not integral";
}
Is there something wrong with the latter way of doing it? Is his way better? Why?
Thanks.
The example below should illustrate the difference. Let's add struct X:
struct X
{
X(int)
{
}
};
and modify one foo as below:
template <typename T> void foo(T t, true_type)
{
std::cout << t << " is integral";
X x(t);
}
template <typename T> void foo(T t, false_type)
{
std::cout << t << " is not integral";
}
Then:
template <typename T> void bar(T t)
{
foo(t, typename is_integral<T>::type());
}
Will still compile for all T types (including integer types; it may cause warning but will compile).
The other equivalent code:
template <typename T> void foo(T t)
{
if(std::is_integral<T>::value)
{
std::cout << "integral";
X x(t);
}
else
std::cout << "not integral";
}
will often fail to compile as you will not be able to instantiate X for types other then integral and eventually floating point and user defined classes which have operator int() (operator short() or operator long() will not do).