首页 > 解决方案 > 为一组类型专门化功能模板

问题描述

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

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

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

当然,对于没有operator<<. 我只想写std::cout幼稚的类型(即数字,,,std:stringconst char *,对于其他类型,没有任何东西可以打印出来。所以,我尝试了这个(为简化起见,我省略了对std:string,的检查const 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 专门化功能模板吗?

PS Boost 是无关紧要的 PPS 我已经看到了这个答案Specialize Many Templates for a Set of Types,但我不知道如何采用它,即所有可能的类型都可以传递给函数,而不仅仅是几个预定义的

标签: c++c++11templatessfinae

解决方案


您可以直接使用 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


推荐阅读