SFINAE (Substitution Failure Is Not An Error)でSubstitutionを行う場所は関数のsignatureならどこでも使えるので、以下のように3種類(template引数、関数引数、戻り値)の書き方が可能です。
#include <iostream>
#include <type_traits>
#include <string>
// 書き方1 (template引数)
template <typename T, class = typename std::enable_if<std::is_fundamental<T>::value>::type>
void f(T t) {
    std::cout << "fundamental type : " << t << std::endl;
}
template <typename T, class = typename std::enable_if<!std::is_fundamental<T>::value>::type>
void f(const T& t) {
    std::cout << "not fundamental type : " << t << std::endl;
}
// 書き方2 (関数引数)
template <typename T>
void g(T t, typename std::enable_if<std::is_fundamental<T>::value>::type* = 0) {
    std::cout << "fundamental type : " << t << std::endl;
}
template <typename T>
void g(const T& t, typename std::enable_if<!std::is_fundamental<T>::value>::type* = 0) {
    std::cout << "not fundamental type : " << t << std::endl;
}
// 書き方3 (戻り値)
template <typename T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type h(T t) {
    std::cout << "fundamental type : " << t << std::endl;
}
template <typename T>
typename std::enable_if<!std::is_fundamental<T>::value, void>::type h(const T& t) {
    std::cout << "not fundamental type : " << t << std::endl;
}
int main() {
    int a = 0;
    std::string str = "string";
    f(a); // fundamental type : 0
    f(str); // not fundamental type : string
    g(a); // fundamental type : 0
    g(str); // not fundamental type : string
    h(a); // fundamental type : 0
    h(str); // not fundamental type : string
}
いずれも、std::enable_if
1番目のtemplate引数に与える方法では、無名のクラスにデフォルトtemplate引数を与えています。
2番目の引数に与える方法では、enable_ifのtypeのポインター型にヌルポインターのデフォルト引数を与えています。
3番目の戻り値を使う方法では、typename std::enable_if
どの書き方もWebや書籍で見たことがあるので、どれを使用するかは好みでいいのだと思います。
