Reputation: 18219
When we do ...
template <typename T>
void foo(T x)
{
if (is_fundamental<T>::value)
{
...
} else
{
...
}
}
I would think that the if
statement (as well as is_fundamental<T>::value
) is evaluated at run time, is that right?
If yes, is there a way to make this evaluation at compilation time? I would like to have something like...
template <primitive_typename T>
void foo(T x)
{
...
}
template <noPrimitive_typename T>
void foo(T x)
{
...
}
One solution would be to overload every possible primitive type but it is not really a satisfying solution as it requires duplicating the code for primitive type many times. Is there no way to refer to all primitives with a a single typename?
Upvotes: 0
Views: 185
Reputation: 66210
What about tag dispatching?
template <typename T>
void fooHelper (T t, std::true_type const &)
{ /* true case */ }
template <typename T>
void fooHelper (T t, std::false_type const &)
{ /* false case */ }
template <typename T>
void foo (T t)
{ fooHelper(t, std::is_fundamental<T>{}); }
Upvotes: 1
Reputation: 119219
In C++17 the if constexpr
statement evaluates the condition at compile time and discards the branch that isn't selected:
if constexpr(std::is_fundamental_v<T>) {
// do something with x
} else {
// do something else with x
}
An old-fashioned way is to use tag dispatch:
template <typename FundamentalType>
void foo_helper(FundamentalType x, std::true_type);
template <typename NonFundamentalType>
void foo_helper(NonFundamentalType x, std::false_type);
template <typename T>
void foo(T x) {
foo_helper(x, std::is_fundamental<T>{});
}
You can also use a partially specialized helper struct, but it's more code.
Upvotes: 8