Question: Suppose I have a template function:

```
template<typename T>
void f(T t)
{
    ...
}

```

and I want to write a specialization for all primitive integer types. What is the best way to do this?

What I mean is:

```
template<typename I where is_integral<I>::value is true>
void f(I i)
{
    ...
}

```

and the compiler selects the second version for integer types, and the first version for everything else?

Answer: 
I would use overload resolution. That spares you from having to use the gross SFINAE hack. Unfortunately there are many areas where you can't avoid it, but this fortunately isn't one of those.

```
template<typename T>
void f(T t)
{
  f(t, std::is_integral<T>());
}

template<typename T>
void f(T t, std::true_type)
{ 
  // ...
}

template<typename T>
void f(T t, std::false_type)
{ 
  // ...
}

```
What about a more straightforward and better readable way by just implementing the different versions inside the function body?

```
    template<typename T>
    void DoSomething(T inVal) {
        static_assert(std::is_floating_point<T>::value || std::is_integral<T>::value, "Only defined for float or integral types");
        if constexpr(std::is_floating_point<T>::value) {
            // Do something with a float
        } else if constexpr(std::is_integral<T>::value) {
            // Do something with an integral
        }
    }

```

You dont have to worry about performance. The conditions are compile time constant and a descent compiler will optimize them away.
"if constexpr" is c++17 unfortunately but you may remove "constexpr" when both versions compile without errors for both types