【发布时间】:2015-06-10 20:44:20
【问题描述】:
我有十几个函数,它们接受两个参数:一个泛型和一个特定类型。例如:
template <class A, class B>
void foo(A& a, B& b)
{
cout << "generic fallback" << endl;
}
template <class A>
void foo(A& a, int &i)
{
cout << "generic int" << endl;
}
template <class A>
void foo(A& a, string& s)
{
cout << "generic str" << endl;
}
我想创建一个重载,只要A 是特定结构[1] 的实例,它就会被调用。到目前为止我想出的最好的是:
struct mine
{
int is_special;
};
template <class A, class B>
auto foo(A& a, B& b) -> decltype(A::is_special, void())
{
cout << "specialized fallback" << endl;
}
我想要的结果是:
int x;
string y;
float z;
string generic;
mine special;
foo(generic, x); // generic int
foo(generic, y); // generic string
foo(generic, z); // generic fallback
foo(special, x); // specialized fallback
foo(special, y); // specialized fallback
foo(special, z); // specialized fallback
但是,上面的代码不起作用,因为对于特殊情况,存在模棱两可的重载。是否有任何简单的方法可以仅在 A::is_special 不是有效类型时才创建这些函数?理想情况下,我会用以下内容注释每个函数:
template <class A, class B>
auto foo(A& a, B& b) -> decltype(doesnt_work(A::is_special), void())
// ...
我还在更一般的情况下问:鉴于任何“肯定”的 SFINAE 测试会导致作为测试结果创建函数或类,有没有办法专门否定该测试以用于其他情况?本质上,相当于if ... else if 和 SFINAE。
我确实让这个案例工作了,但我必须将所有 foo 重命名为 foo_imp,将 long 参数添加到通用参数,将 int 参数添加到专用参数,然后定义一个foo 调用它们(ideone 代码 here)。这似乎不太理想,因为它并不那么简单,尽管无论如何我都必须修改所有现有的foos。
[1] 请注意,我不能使用该类型的名称,因为它是一个嵌套模板,因此会导致不可推断的上下文。
【问题讨论】:
标签: c++ templates c++11 generics sfinae