Name conflict between template structure and template member function

Next, GCC mixes the struct name template with the function of the template member name class A , while Clang compiles fine ( 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>(); } 

The function f apparently intended to be called with an argument of type A in this example, but it could be anything, so f should remain a template function.

I don't care which compiler is correct, I only need a workaround because I really don't know any syntax except

 x.template name<B>(); 

to call a member function, and I don’t see how using a declaration or any other way of disambiguating can be applied.

EDIT Yes, now I tried a more explicit syntax

 xT::template name<B>(); 

which works but really ugly. Any way to make a concise syntax work? Otherwise, it would be preferable to change one of the two names to start with ...

EDIT2 My initial version of f works with a universal T&& link that needs the ugliest

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

in case T is a reference ... And all this for a simple function call.

+7
c ++ templates template-function
source share
3 answers

I thought about this a bit and I see no way to make the basic syntax you want to work due to all the templates involved. The reason you should specify template is because otherwise it looks at the compiler as you use < to compare the address of the function with B

As you said, you can simply rename one of the name identifiers, letting the compiler not have any ambiguity about what you mean.

Alternatively, you can do what you said and fully qualify the call. I do not consider this an ugly syntax: it reads clearly what is happening, and in the end you only need to write a function once.

 template<bool B, typename T> void f(T& x) { typedef typename std::remove_reference<T>::type callee; x.callee::template name<B>(); } 

Finally, if you can talk a little more about the real problem that you are trying to solve with this template, we could offer an orthogonal solution that is not associated with such a type alias at all.

+1
source share

EDIT: As indicated by the constructor and iavr, the following non-standard behavior:


With VS2013, the following work is done:

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

exit:

  A::name() called with B=1 
0
source share

You can also use a namespace.

Put the "structure name" in the namespace, and then refer to the structure name as NS :: name.

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

You can use your original name x.template () with this method.

0
source share

All Articles