当我尝试从以下代码创建可执行文件时出现链接器错误。我得到的印象是我需要放置一些“typename
s”或做出一些前瞻性声明;我尝试过几种组合但没有效果。
template<typename T>
class enabled
{
private:
T type_;
friend const T& typeof(const enabled<T>& obj); // Offending line
};
template<typename T>
const T& typeof(const enabled<T>& obj) {
return obj.type_;
}
int main()
{
enabled<std::string> en;
std::cout << typeof(en);
std::cin.clear(), std::cin.get();
return 0;
}
1&gt; main.obj:错误LNK2001:未解析的外部符号“class std :: string const&amp; __cdecl typeof(启用类&lt;类std :: string&gt; const&amp;)”
答案 0 :(得分:4)
通过前向声明并指定该函数是模板化的
template<typename T> class enabled;
template<typename T>
const T& typeof(const enabled<T>& obj) {
return obj.type_;
}
template<typename T>
class enabled
{
private:
T type_;
friend const T& typeof<>(const enabled<T>& obj);
};
答案 1 :(得分:3)
问题在于,作为类的朋友的函数不是函数模板,而实际定义的函数是函数模板。
您需要做的就是将朋友的功能模板设为:
template<typename T>
class enabled
{
private:
T type_;
template<typename U> //<-------------------------------note this
friend const U& typeof_(const enabled<U>& obj); //use U
};
现在编译得很好:http://www.ideone.com/VJnck
但是它会typeof_<U>
enabled<T>
所有实例化的typeof_<int>
朋友的所有实例化,这意味着enabled<T>
是T
的朋友template<typename T>
class enabled
{
private:
T type_;
friend const T& typeof_(const enabled<T>& obj)
{
return obj.type_;
}
};
的所有可能值反之亦然。
因此,更好的解决方案是使函数非模板和在类中定义它:
typeof
演示:http://www.ideone.com/Rd7Yk
请注意,我将typeof_
替换为typeof
,因为GCC的扩展名为{{1}},因此它在ideone上出错(因为我无法关闭扩展名)。