7

在下文中,GCC 将模板结构与类name的模板成员函数混淆,而 Clang 编译良好(现场示例):nameA

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应用声明或任何其他消歧方式。

编辑是的,我现在尝试了更明确的语法

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

这有效,但真的很难看。有什么方法可以使简短的语法起作用吗?否则,最好将两个名称之一更改为...

EDIT2我的原始版本f适用于通用参考T&&,需要最丑陋的

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

万一T是一个参考......而这一切都是为了一个简单的函数调用。

4

3 回答 3

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>();
}

最后,如果您可以详细说明您尝试使用此模板解决的实际问题,我们可能能够提供一个完全不涉及此类类型别名的正交解决方案。

于 2014-06-20T18:47:36.283 回答
0

您还可以使用命名空间。

将“结构名称”放在命名空间中,然后将结构名称称为 NS::name。

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

您可以将原始 x.template name() 与此类方法一起使用。

于 2014-07-28T02:02:35.803 回答
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
于 2014-03-22T10:47:08.107 回答