2

I have a template class with the following structure

//CFoo.hpp (header file)
template <typename T>
class CFoo {
        struct SFoo {
            T *ptr;
            /* rest is irrelevant */
        } *foo;

    public:
    /* omitting irrelevant parts */
    SFoo* get();
};

Now, if I implement the method SFoo* get() inside header file everything works nice. However, if I separate declaration and definition my code stops working with the followingg compilation errors.

//CFoo.cpp (source code, example 1)
/* omitting irrelevant parts */
template <typename T>
SFoo* CFoo<T>::get() { return foo; } //ERROR HERE

Error: <where-is-the-error>: error: ‘SFoo’ does not name a type

//CFoo.cpp (source code, example 2)
/* omitting irrelevant parts */
template <typename T>
CFoo<T>::SFoo* CFoo<T>::get() { return foo; } //ERROR HERE

Error: <where-is-the-error>: error: need ‘typename’ before ‘CFoo<T>::SFoo’ because ‘CFoo<T>’ is a dependent scope

I'm looking forward to any hints on how to fix that. Thanks in advance.

Robin92
  • 533
  • 1
  • 6
  • 20

3 Answers3

5

You have to qualify dependent types using typename. See Where and why do I have to put the "template" and "typename" keywords?

//CFoo.cpp (source code, example 2)
/* omitting irrelevant parts */
template <typename T>
typename CFoo<T>::SFoo* CFoo<T>::get() { return foo; }
^^^^^^^^

In C++11 you can use auto instead since SFoo will be in scope after the function name

template <typename T>
auto CFoo<T>::get() -> SFoo* { return foo; }
Community
  • 1
  • 1
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • Now all C++ needs to do is replace `auto` by the keywords `function` and `var` and we have us a decent language going. `var x = 1;` … `function foo() -> int { return 42; }` – Konrad Rudolph Dec 22 '12 at 12:16
1

You need to fully qualify SFoo when outside of the class declaration: typename CFoo<T>::SFoo.

pmr
  • 58,701
  • 10
  • 113
  • 156
1

In general, typename has to be used whenever a name that depends on a template parameter is a type.

template <typename T>
typename CFoo<T>::SFoo* CFoo<T>::get() { return foo; }

§ 14.6.2 Name resolution

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

billz
  • 44,644
  • 9
  • 83
  • 100