1

If I keep the function Find() inlined, then the program compiles. Otherwise, as shown below, it does not compile.

Is it possible to separate the declaration and implementation of such:

//////////////////////////////////////////////////////////////////////////
template <class T>
class MyClass
{
public:
    struct MyStruct
    {
        int id;
        T value;
    };

    MyStruct *Find(int id);

private:
};

template<class T>
MyClass<T>::MyStruct *Find(int id)
{
    return nullptr;
}

//////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
    MyClass<int> c;

    c.Find(2);
    return 0;
}
BenS
  • 41
  • 7

3 Answers3

3

You need to qualify your return value with typename and the implementation needs to be qualified as a member of MyClass.

template<class T>
typename MyClass<T>::MyStruct * MyClass<T>::Find(int id)
{
    return nullptr;
}
Community
  • 1
  • 1
lcs
  • 4,227
  • 17
  • 36
1

Yes, it is possible, as long as you keep them in the same file. If you try to separate the definition in a different source file, you'll most likely going to end up with linker errors (unless you provide explicit instantiations and use only the latter in your code).

You get a compile error because you need typename in

typename MyClass<T>::MyStruct

as the latter is a dependent name. In the inline case, the name MyClass<T> is injected and it is relative to the instantiation, so there is no need to explicitly specify the template parameter.

EDIT As @cocarin mentioned, you also need to qualify MyClass<T>::Find(int id), since it is a member function of MyClass<T>. However, if you don't, the program will still compile but won't link. That's because you end up defining a global function Find, then try to invoke the member function, which ends up not being defined.

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
1

You should write:

template<class T>
typename MyClass<T>::MyStruct * MyClass<T>::Find(int id)
{
    return nullptr;
}

or, since C++11

template<class T>
auto MyClass<T>::Find(int id)
-> MyStruct* /* no need of typename MyClass<T>:: here :) */
{
    return nullptr;
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302