Compile error for non-inline member function of inner class of templatized class

I've got a template class B with an inner class A. Class A has a member function f that I want to return a reference to itself (i.e., a reference to an object of type A). I keep getting inexplicable compiler errors.

Here's what I know:

If I change the return type to void it compiles.
If I get rid of the outer class, it compiles.
If I get rid of the templates, it compiles.
If I move the function implementation into the class declaration, it compiles. (This technique actually gets me what I want, I just like keeping my method implementations out of the class declaration as a matter of style.)

Here are two versions of the classes in one file -- the first I changed the return type to void just to show the problem is with the return type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
matt@meteor:cpp$ cat -n error.cpp
     1  // THIS COMPILES FINE
     2
     3  template<typename T>
     4  class B1 {
     5      public:
     6          class A1 {
     7                  int _a;
     8              public:
     9                  void f(const A1& a);
    10          };
    11  };
    12
    13  template<typename T>
    14  inline void B1<T>::A1::f(const A1& a) {
    15      _a = a._a;
    16  }
    17
    18  // BUT THIS DOES NOT COMPILE
    19
    20  template<typename T>
    21  class B2 {
    22      public:
    23          class A2 {
    24                  int _a;
    25              public:
    26                  A2& f(const A2& a);
    27          };
    28  };
    29
    30  template<typename T>
    31  inline B2<T>::A2& B2<T>::A2::f(const A2& a) {
    32      _a = a._a;
    33      return *this;
    34  }
matt@meteor:cpp$ g++ -c -Wall error.cpp
error.cpp:31: error: expected initializer before ‘&’ token
matt@meteor:cpp$ g++ --version
g++.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3



Anybody see what I'm doing wrong here?

Much thanks,
Matt Busche
inline typename B2<T>::A2& B2<T>::A2::f(const A2& a) { solved it. When you do :: while using templates C++ has problems recognizing what the thing after :: is. Maybe this makes sense because due to template specialization Foo<int>::Bar could be a type while Foo<char>::Bar was a static variable..

By the way, these are the errors MSVC++ found:
main.cpp(12): warning C4346: 'B2<T>::A2' : dependent name is not a type
          prefix with 'typename' to indicate a type
main.cpp(12): error C2143: syntax error : missing ';' before '&'
main.cpp(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Last edited on
Thanks hamsterman,

gnu clearly needs to improve their warning/error messaging. What a nightmare. The sad thing is I now remember reading about this usage for typename a few years back; but since I've never previously had the need for it, I guess it didn't really sink in.

Matt
$ g++ error.cpp
error: need ‘typename’ before ‘B2<T>::A2’ because ‘B2<T>’ is a dependent scope
I think that it is clear enought. (version 4.6.1)
Last edited on
Topic archived. No new replies allowed.