未解析的非模板方法被正确实例化的模板方法调用
Unresolved NON template method being called by template method which is correctly instantiated
在决定问这个问题之前,我搜索了整个互联网和堆栈溢出,所以如果我忽略了一些非常简单的事情,请原谅,但就在这里。
使用 Visual Studio 2010,我有一个 class 这样的:
class MyClass {
public:
/* Constructors and other methods omitted */
template <typename T1>
CString operator()(const T1 &a1) { return _fmt("dummy", a1); }
template <typename T1, typename T2>
CString operator()(const T1 &a1, const T2 &a2) { return _fmt("dummy", a1, a2); }
template <typename T1, typename T2, typename T3>
CString operator()(const T1 &a1, const T2 &a2, const T3 &a3) { return _fmt("dummy", a1, a2, a3); }
template <typename T1, typename T2, typename T3, typename T4>
CString operator()(const T1 &a1, const T2 &a2, const T3 &a3, const T4 &a4) { return _fmt("dummy", a1, a2, a3, a4); }
private:
CString _fmt(const char *dummy, ...);
};
想法是为 MyClass 提供一个 operator ()
重载,其作用类似于 sprintf() 格式化程序,只是格式字符串包含在 MyClass 实例本身中。我会使用可变参数模板,可惜 Visual Studio 2010 不支持它们,因此半生不熟的解决方案是提供许多 operator ()
的重载模板版本,这些版本又会调用私有 _fmt()
使用 va_list/va_start()/va_end()
的函数因此需要一个无用的第一个参数(因此名称 "dummy")。
编译正常,但是链接会出现如下错误:
error LNK2019: unresolved external symbol "private: class ATL::CStringT<char,class ATL::StrTraitATL<char,class ATL::ChTraitsCRT<char> > > __cdecl MyClass::_fmt(char const *,...)" (?_fmt@MyClass@@AAA?AV?$CStringT@DV?$StrTraitATL@DV?$ChTraitsCRT@D@ATL@@@ATL@@@ATL@@PBDZZ) referenced in function "public: class ATL::CStringT<char,class ATL::StrTraitATL<char,class ATL::ChTraitsCRT<char> > > __thiscall MyClass::operator()<char [261]>(char const (&)[261])" (??$?R$$BY0BAF@D@MyClass@@QAE?AV?$CStringT@DV?$StrTraitATL@DV?$ChTraitsCRT@D@ATL@@@ATL@@@ATL@@AAY0BAF@$$CBD@Z)
我从上面的消息中了解到,模板化运算符已正确实例化,并且它包含对 _fmt()
方法的调用,但是链接器无处可寻。
但是_fmt()
是包含在一个.cpp文件中,是被编译和喜欢,实际上是构造函数也在那里定义,链接器不会抱怨它。
我发现解决这个问题的唯一方法是将 _fmt()
代码放在头文件中的 class 定义体中,这很丑陋。
有什么想法吗?
好吧,这是一个愚蠢的问题,但由于其他人可能会以某种方式偶然发现它,所以我正在回答我自己的问题。
我错误地包含了头文件 <afxmt.h>
,它是 MFC 的一部分,以便获得 CCriticalSection
class 定义,而项目的其余部分使用 ATL ,这带来了不同版本的 CString。但是,不知何故,这只影响了 MyClass 实现文件,而其他人,即使他们使用的是 MyClass,也得到了不同版本的 CString。
我通过不包括 <afxmt.h>
并自己实现 CCriticalSection
class 来解决它。
在决定问这个问题之前,我搜索了整个互联网和堆栈溢出,所以如果我忽略了一些非常简单的事情,请原谅,但就在这里。
使用 Visual Studio 2010,我有一个 class 这样的:
class MyClass {
public:
/* Constructors and other methods omitted */
template <typename T1>
CString operator()(const T1 &a1) { return _fmt("dummy", a1); }
template <typename T1, typename T2>
CString operator()(const T1 &a1, const T2 &a2) { return _fmt("dummy", a1, a2); }
template <typename T1, typename T2, typename T3>
CString operator()(const T1 &a1, const T2 &a2, const T3 &a3) { return _fmt("dummy", a1, a2, a3); }
template <typename T1, typename T2, typename T3, typename T4>
CString operator()(const T1 &a1, const T2 &a2, const T3 &a3, const T4 &a4) { return _fmt("dummy", a1, a2, a3, a4); }
private:
CString _fmt(const char *dummy, ...);
};
想法是为 MyClass 提供一个 operator ()
重载,其作用类似于 sprintf() 格式化程序,只是格式字符串包含在 MyClass 实例本身中。我会使用可变参数模板,可惜 Visual Studio 2010 不支持它们,因此半生不熟的解决方案是提供许多 operator ()
的重载模板版本,这些版本又会调用私有 _fmt()
使用 va_list/va_start()/va_end()
的函数因此需要一个无用的第一个参数(因此名称 "dummy")。
编译正常,但是链接会出现如下错误:
error LNK2019: unresolved external symbol "private: class ATL::CStringT<char,class ATL::StrTraitATL<char,class ATL::ChTraitsCRT<char> > > __cdecl MyClass::_fmt(char const *,...)" (?_fmt@MyClass@@AAA?AV?$CStringT@DV?$StrTraitATL@DV?$ChTraitsCRT@D@ATL@@@ATL@@@ATL@@PBDZZ) referenced in function "public: class ATL::CStringT<char,class ATL::StrTraitATL<char,class ATL::ChTraitsCRT<char> > > __thiscall MyClass::operator()<char [261]>(char const (&)[261])" (??$?R$$BY0BAF@D@MyClass@@QAE?AV?$CStringT@DV?$StrTraitATL@DV?$ChTraitsCRT@D@ATL@@@ATL@@@ATL@@AAY0BAF@$$CBD@Z)
我从上面的消息中了解到,模板化运算符已正确实例化,并且它包含对 _fmt()
方法的调用,但是链接器无处可寻。
但是_fmt()
是包含在一个.cpp文件中,是被编译和喜欢,实际上是构造函数也在那里定义,链接器不会抱怨它。
我发现解决这个问题的唯一方法是将 _fmt()
代码放在头文件中的 class 定义体中,这很丑陋。
有什么想法吗?
好吧,这是一个愚蠢的问题,但由于其他人可能会以某种方式偶然发现它,所以我正在回答我自己的问题。
我错误地包含了头文件 <afxmt.h>
,它是 MFC 的一部分,以便获得 CCriticalSection
class 定义,而项目的其余部分使用 ATL ,这带来了不同版本的 CString。但是,不知何故,这只影响了 MyClass 实现文件,而其他人,即使他们使用的是 MyClass,也得到了不同版本的 CString。
我通过不包括 <afxmt.h>
并自己实现 CCriticalSection
class 来解决它。