3

(This question is only a duplicate of the other question if you already know the answer!)

(Please note my follow-up question: Why is no template keyword needed if an unrelated global template function with same name exists?)

I get a compiler error at the indicated line when I try to compile templated C++ code with this structure:

template <int N>
struct A {
    template <int i>
    void f() {};
};

template <int N>
struct B {
    A<N> a;

    B(A<N>& a) : a(a) {}

    void test() {
        a.f<1>();  // does not compile
    }
};

int main() {
    A<2> a;
    a.f<1>();   // works fine
    B<2> b(a);
    b.test();
}

g++ says:

test2.cpp: In member function ‘void B<N>::test()’:
test2.cpp:14: error: expected primary-expression before ‘)’ token
test2.cpp: In member function ‘void B<N>::test() [with int N = 2]’:
test2.cpp:22:   instantiated from here
test2.cpp:14: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’

clang++ says:

test2.cpp:14:16: error: expected expression
        a.f<1>();  // does not compile
           ^
1 error generated.

The same expression works in the context of main(), but not within the test() method of the templated class B, which has an instance of A as a private variable. I am pretty clueless why this doesn't work.

Community
  • 1
  • 1
Stefan
  • 4,380
  • 2
  • 30
  • 33

1 Answers1

5

You have to use a.template f<1>(); inside of b.test().

Ivan Vergiliev
  • 3,771
  • 24
  • 23
  • 2
    And this is why C++ is such a wonderful language! I sort of knew the answer but still couldn't come up with it offhand--I thought the `template` was going to go before `a.` rather than after it. Black magic, this--I've never needed it in a decade of practice. – John Zwinck May 27 '14 at 12:58
  • Yes, that does the trick. Thanks! I'll read up on when I have to use the `template` and `typename` keywords. So far, the compiler was pretty explicit in suggesting that these keywords were required, but not this time I guess... – Stefan May 27 '14 at 13:01
  • @JohnZwinck No black magic there: `template` does not go "after `a.`", it goes "before `f<:::>`"; it tells the compiler that the following thing is a template. And why is it necessary? Because (the type of) `a` depends on a template parameter, so when parsing the template definition, the compiler doesn't yet know what the type of `a` will be and thus what its members are. So it needs to be told to treat `<` as "template argument bracket" and not "less than." – Angew is no longer proud of SO May 27 '14 at 13:24
  • @Angew: Speaking of "black magic", maybe you want to chime in on my follow-up question: http://stackoverflow.com/questions/23892498/why-is-no-template-keyword-needed-if-an-unrelated-global-template-function-with – Stefan May 27 '14 at 16:42