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



下面,GCC混淆了模板结构体nameA类的模板成员函数name,而Clang编译得很好(实例):

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需要保持为模板函数。

我不太关心哪个编译器是正确的,我只需要一个变通方法,因为除了

我真的不知道任何语法
x.template name<B>();

来调用成员函数,我看不出using声明或任何其他消歧方式如何适用。

EDIT是的,我现在尝试了更显式的语法

x.T::template name<B>();

可以工作,但是真的很丑。有什么办法使简短的语法工作吗?否则,最好将两个名称中的一个改为以…

开头。

EDIT2我的原始版本f工作在通用引用T&&上,它需要最丑的

using X = typename std::remove_reference<T>::type;
x.X::template name<B>();

的情况下T是一个引用…这一切都是为了一个简单的函数调用。

我想了一下,由于所有涉及的模板,我看不到任何方法可以使你想要的最基本的语法工作。您必须指定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>();
}

最后,如果你能更详细地说明你试图用这个模板解决的实际问题,我们可能能够提供一个正交解决方案,根本不涉及这种类型混叠

编辑:正如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

您也可以使用命名空间。

将"结构名"放在命名空间中,然后将结构名引用为NS::name。

namespace NS
{
    template<typename T>
    struct name {};
}

你可以使用你原来的x.template name()方法

相关内容

  • 没有找到相关文章

最新更新