在 C++ 中使用模板和嵌套类型分离实现和声明

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

如果我保持内联函数 Find(),则程序可以编译。否则如下图,编译不通过

是否可以将这样的声明和实现分开:

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

是的,有可能,as long as you keep them in the same file。如果您尝试在不同的源文件中分离定义,您很可能会以 linker 错误结束(除非您提供显式实例化并在代码中仅使用后者)。

你得到一个编译错误,因为你需要 typename in

typename MyClass<T>::MyStruct

因为后者是 dependent name。内联情况下注入的名字MyClass<T>是相对于实例化的,所以不需要显式指定模板参数

EDIT 正如@cocarin 提到的,您还需要限定 MyClass<T>::Find(int id),因为它是 MyClass<T> 的成员函数。但是,如果您不这样做,该程序仍会编译但不会 link。那是因为你最终定义了一个全局函数Find,然后尝试调用成员函数,最终没有被定义。

您需要使用 typename 限定您的 return 值,并且实施需要限定为 MyClass.

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

你应该写:

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

或者,自 C++11

template<class T>
auto MyClass<T>::Find(int id)
-> MyStruct* /* no need of typename MyClass<T>:: here :) */
{
    return nullptr;
}