5

I try to compile the following with g++ 4.7.2:

template <typename T>
struct A {
    struct B {
        T t;

        template<T B::*M>
        T get() {
            return this->*M;
        }
    };

    B b;

    T get() {
        return b.get<&B::t>();
    }
};


int main() {
    A<int> a;
    a.get();
}

It gives me

test.cpp: In member function ‘T A<T>::get()’:
test.cpp:15:23: error: expected primary-expression before ‘)’ token
test.cpp: In instantiation of ‘T A<T>::get() [with T = int]’:
test.cpp:22:8:   required from here
test.cpp:15:23: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int A<int>::B::*’ to binary ‘operator<’

Why?

Thanks.

Paul Draper
  • 78,542
  • 46
  • 206
  • 285

1 Answers1

14

You need to use the template disambiguator:

return b.template get<&B::t>();

Without it, when parsing the expression:

b.get<&B::t>();

The compiler can't tell whether it should interpret get as the name of a member variable followed by a < sign (less-than), or as the instantiation of a member function template called get.

Although we know what is the intended meaning of our expression, the compiler cannot, at least not before instantiation occurs - and syntactic parsing is performed even though your function is never instantiated.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • And just when you know C++... When I am I supposed to use "template disambiguation"? (I just searched, but I can't seem to find a good answer on this.) – Paul Draper Mar 28 '13 at 23:22
  • 3
    @PaulDraper: Actually, I found [this Q&A](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) which should explain it quite well. – Andy Prowl Mar 28 '13 at 23:23
  • 1
    Excellent. That also includes the explanation for `typename`, which I have also not fully understood. – Paul Draper Mar 28 '13 at 23:31