模板结构和模板成员函数之间的名称冲突

时间:2014-03-11 00:23:11

标签: c++ templates template-function name-conflict

在下文中,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是一个引用......所有这些都是一个简单的函数调用。

3 个答案:

答案 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名称()和这种方法。