在下面,struct Y重载X的成员函数f.两个重载都是模板函数,但是要明确指定不同的参数(typename和int):
struct X { template <typename> static bool f() { return true; } }; struct Y : public X { using X::f; template <int> static bool f() { return false; } }; int main() { std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl; }
这按照预期使用gcc打印10.然而,clang(3.3)抱怨说
[...] error: no matching function for call to 'f' std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl; ^~~~~~~~~~~ [...] note: candidate template ignored: invalid explicitly-specified argument for 1st template parameter template <int> static bool f() { return false; } ^
即,只能看到Y的版本.我试过了
using X::template f;
解决方法
最近根据另一个答案向我解释了这个难题.
来自#clang IRC频道:
[01:16:23] <zygoloid> Xeo: this is a weird corner of the language where clang conforms but the rule is silly [01:16:31] <Xeo> ... really? :( [01:16:45] <zygoloid> Xeo: when deciding whether a using-declaration is hidden,we're not allowed to look at the template-parameter-list (nor the return type,iirc) [01:17:04] <zygoloid> so the derived class declaration of operator()(T) suppresses the using-declaration [01:17:19] <Xeo> because it has the same signature / parameter types? [01:17:40] <zygoloid> rigth
解决方法是不在使用派生版本的类中定义f.相反,将它移动到一个辅助助手类(在这种情况下,它会引发问题,你认为哪个定义应该获胜).
>请参阅此处查看我之前遇到的有问题的案例:Lambda functions as base classes
07001
>以及如何使用额外的基类修复它:
07002
致谢感谢@Xeo和Lounge中的人们发掘这个“愚蠢的规则”