简体   繁体   中英

Separate implementation and declaration with templates and nested types in C++

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;
}

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;
}

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM