以下代码在 VS2015 上可以正常工作:
struct Foo
{
using Bar = int;
auto operator()() { return "Foo!"; }
};
template <typename Callable, typename CodeType> // <<< CodeType is a template param
void funky(CodeType code, Callable func)
{
cout << "Generic: " << code << ", " << func() << endl;
}
template <typename HasBar>
void funky(typename HasBar::Bar code, HasBar func) // <<< The code type is a nested type
{
cout << "Has Bar: " << code << ", " << func() << endl;
}
int main()
{
Foo foo;
funky(3, []() { return "Lambda!"; });
funky(3, foo);
return 0;
}
打印:
Generic: 3, Lambda!
Has Bar: 3, Foo!
然而,it does not compile在 gcc/clang 上,提示:
In function 'int main()':
27:16: error: call of overloaded 'funky(int, Foo&)' is ambiguous
27:16: note: candidates are:
12:6: note: void funky(CodeType, Callable) [with Callable = Foo; CodeType = int]
18:6: note: void funky(typename HasBar::Bar, HasBar) [with HasBar = Foo; typename HasBar::Bar = int]
歧义由 VS2015 正确解决(这并不意味着它是符合要求的事情)。
我怎样才能让它在 Clang/gcc 上正确编译和运行?
我想过使用 std::enable_if
但无法让它做我想做的事(我很可能使用不正确)。如果这是要走的路,应该如何使用它来解决这种歧义?
更新:
将 typename HasBar::Bar 添加到模板参数中可以让 gcc/Clang 正确构建和运行代码:
template <typename HasBar, typename HasBar::Bar>
void funky(typename HasBar::Bar code, HasBar func) // <<< The code type is a nested type
{
cout << "Has Bar: " << code << ", " << func() << endl;
}
这似乎告诉编译器还有第二个非类型模板参数值(在函数代码中未使用),类型为 typename HasBar::Bar
。 如果 typename HasBar::Bar
不存在,SFINAE 将从重载集中删除该函数,并选择泛型形式。
但是,当它确实存在时,我不知道为什么这个函数会优先于第一个。我猜是因为它更专业——尽管代码本身没有使用特化。 然而,在这种情况下,它甚至在新参数出现之前就已经更加特化了!
但是,在这种情况下,VS2015 总是选择给出错误答案的通用形式!
是否有一些语法(和/或解决方法)适用于所有情况?
最佳答案
13 分钟后...回答我自己。 [NOT] 已解决!
将 typename HasBar::Bar
添加到模板参数 did the trick :
template <typename HasBar, typename HasBar::Bar>
void funky(typename HasBar::Bar code, HasBar func) // <<< The code type is a nested type
{
cout << "Has Bar: " << code << ", " << func() << endl;
}
这似乎告诉编译器还有第二个非类型模板参数值(在函数代码中未使用),类型为 typename HasBar::Bar
。如果 typename HasBar::Bar
不存在,SFINAE 将从重载集中删除此函数,并选择通用形式。
但是,当它确实存在时,我不知道为什么这个函数会优先于第一个。我猜是因为它更特化——尽管代码本身没有使用特化。
然而,在这种情况下,它甚至在新参数出现之前就已经更加特化了!
关于c++ - 基于嵌套类型的模板函数选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37276525/