为类型集专门化函数模板

Specialize function template for set of types

是否可以为不同的 类型创建具有不同行为的函数模板?

假设一个带有模板参数的函数,应该接受任何类型,没有编译失败

template<typename T>
void foo(T arg){
    std::cout << arg;
} 

当然,这不会为没有 operator<< 的类型编译。我只想在 std::cout 中编写朴素类型(即数字、std:stringconst char *),对于其他类型,没有什么可以打印出来的。 所以,我尝试了这个(为了简化,我省略了对 std:stringconst char *

的检查
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
void foo(T arg){
    std::cout << arg;
}

template<typename T, typename = typename std::enable_if<!std::is_arithmetic<T>::value, T>::type>
void foo(T arg){

}

也就是说,必须生成没有潜在歧义的重载函数。当然,代码不会编译,因为模板的参数不是模板签名的一部分(因此有两个模板具有相同的签名)。那么有什么办法可以玩吗?

我看到了将后者函数作为主模板的解决方案,并为声明的类型创建模板特化,但我不想用相同的定义来膨胀我的代码(并且可能会有更多类型用于打印).有什么方法可以使用 std::enable_if 或 smth 来专门化函数模板?

P.S。升压无关紧要 P.P.S。我看过这个答案 ,但我不知道如何采用它,即所有可能的类型都可以传递给函数,而不仅仅是少数预定义的

您是否尝试过使用 std::enable_if 和 return 类型的 SFINAE?

template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type foo(T arg)
 { std::cout << arg; }

template<typename T>
typename std::enable_if<!std::is_arithmetic<T>::value>::type foo(T arg)
 { }

或代码调度?

template <typename T>
void foo_helper (T arg, std::true_type const &)
 { std::cout << arg; }

template <typename T>
void foo_helper (T arg, std::false_type const &)
 { }

template <typename T>
void foo (T arg)
 { foo_helper(arg, std::is_arithmetic<T>{}); }

(注意:代码未经测试)

您可以直接对 SFINAE 使用所需的表达式 std::cout << arg。示例:

template<typename T>
auto foo_imp(T&& arg, int) -> decltype(std::cout << std::forward<T>(arg), throw) /* -> is void */ {
    std::cout << std::forward<T>(arg);
}

template<typename T>
void foo_imp(T&&, long) {
    // Do nothing.
}

template<typename T>
void foo(T&& arg)  {
    foo_imp(std::forward<T>(arg), 0); // int is the best match for 0.
}

struct X {};

int main() {
    foo(1);   // calls foo_imp(int&&, int)
    foo(X{}); // calls foo_imp(X&&, long)
}

上面std::forward用来迂腐地保留arg的值类。

试试这个:

#include <iostream>

template<typename T, typename std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
void foo(T arg){
    std::cout << arg << '\n';
}

template<typename T, typename std::enable_if_t<!std::is_arithmetic<T>::value, int> = 0>
void foo(T arg){
    std::cout << "not an arithmetic type\n";
}

int main() {
    foo(4.6);
    foo("bla");
}

这需要 C++14(对 C++11 使用 std::enable_if),并输出:

4.6
not an arithmetic type

有什么区别?

如果满足条件,我们在这里创建一个默认值为 0 的 int 作为第二个模板参数。