在下文中,GCC将模板结构name
与类name
的模板成员函数A
混淆,而Clang编译正确(live example):
template<typename T>
struct name {};
struct A
{
template<bool B>
void name() { }
};
template<bool B, typename T>
void f(T& x) { x.template name<B>(); }
在本例中,函数f
显然是要使用类型A
的参数调用,但它可能是其他任何东西,因此f
需要保留模板函数。 / p>
我不关心哪个编译器是正确的,我只需要一个解决方法,因为除了
之外我真的不知道任何语法x.template name<B>();
调用成员函数,我无法看到using
声明或任何其他消除歧义的方式如何适用。
编辑是的,我现在尝试了更明确的语法
x.T::template name<B>();
哪个有效,但真的很难看。有什么办法让简短的语法有效吗?否则,最好将两个名称中的一个更改为以......开头。
EDIT2 我的f
原始版本适用于通用引用T&&
,需要 ugliest
using X = typename std::remove_reference<T>::type;
x.X::template name<B>();
如果T
是一个引用......所有这些都是一个简单的函数调用。
答案 0 :(得分:1)
我已经考虑过这一点,由于涉及所有模板,我无法找到任何方法来制作您想要的最基本语法。您必须指定template
的原因是因为它会使编译器看起来像使用<
将函数的地址与B
进行比较。
正如您所说,您可以简单地重命名name
个标识符之一,从而使编译器不会对您指的是哪一个不明确。
或者,您可以完全按照您的说法完成操作并完全符合要求。我发现这不是一种丑陋的语法:读者完全清楚完全发生了什么,毕竟你只需编写一个函数时间。
template<bool B, typename T>
void f(T& x)
{
typedef typename std::remove_reference<T>::type callee;
x.callee::template name<B>();
}
最后,如果您可以详细说明您尝试使用此模板解决的实际问题,我们可能会提供一个根本不涉及此类型别名的正交解决方案。
答案 1 :(得分:0)
编辑:正如Constructor和iavr所指出的,以下是非标准行为:
使用VS2013可以实现以下功能:
template<typename T>
struct name {};
struct A
{
template<bool B>
void name() {
std::cout << "A::name() called with B=" << B<< std::endl;
}
};
template<bool B, typename T>
void f(T& x) { x.name<B>(); }
int main(){
A a;
f<true>(a);
}
输出:
A::name() called with B=1
答案 2 :(得分:0)
您也可以使用命名空间。
将“struct name”放在命名空间中,然后将struct name称为NS :: name。
namespace NS
{
template<typename T>
struct name {};
}
您可以使用原始的x.template名称()和这种方法。