如果我保持函数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;
}
答案 0 :(得分:3)
您需要使用typename
限定返回值,并且实施需要被视为MyClass
的成员。
template<class T>
typename MyClass<T>::MyStruct * MyClass<T>::Find(int id)
{
return nullptr;
}
答案 1 :(得分:1)
是的,有可能,as long as you keep them in the same file。如果您尝试在不同的源文件中分离定义,则最有可能最终会出现链接器错误(除非您提供显式实例化并在代码中仅使用后者)。
您收到编译错误,因为
中需要typename
typename MyClass<T>::MyStruct
因为后者是dependent name。在内联案例中,注入名称MyClass<T>
并且它与实例化相关,因此无需显式指定模板参数。
编辑正如@cocarin所提到的,您还需要限定MyClass<T>::Find(int id)
,因为它是MyClass<T>
的成员函数。但是,如果不这样做,程序仍将编译但不会链接。那是因为你最终定义了一个全局函数Find
,然后尝试调用成员函数,最终没有被定义。
答案 2 :(得分:1)
你应该写:
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;
}