我在一个模板化类上工作,其方法定义在cpp文件中。现在,我想添加另一个仅对某些类模板参数启用的方法。我目前的做法:
template <typename T>
class MyClass
{
template <typename U = T,
typename std::enable_if<std::is_same<SpecialType, U>::value>::type* = 0>
T& Foo();
}
template <typename T>
template <typename U,
typename std::enable_if<std::is_same<SpecialType, U>::value>::type*>
T& MyClass<T>::Foo()
{
// Implementation...
}
// Exported explicit instantiations
template class __declspec(dllexport) MyClass<SpecialType>;
template class __declspec(dllexport) MyClass<OtherType>;
...
这在实现cpp和包含标头的站点中都可以正常编译。问题出在链接器上,我无法解析外部符号。
error LNK2019: unresolved external symbol
"public: class SpecialType & __cdecl MyClass<class SpecialType>::Foo<class SpecialType,0>(void)"
(??$Foo@VSpecialType@@$0A@@?$MyClass@VSpecialType@@@@QEAAAEAVSpecialType@@XZ) referenced in function MyFunction
是什么问题?顺便说一句:其他non-enable_if方法链接很好。
声明Foo
的方式需要像Foo<>()
那样调用,这不理想。
现在,我想添加另一个仅对某些类模板参数启用的方法。
另一种实现方法是专门针对SpecialType
的类的一个(派生的)部分:
struct SpecialType;
template<typename T>
struct MyClassCommon {};
// Generic version.
template<typename T>
struct MyClass : MyClassCommon<T> {
using MyClassCommon<T>::MyClassCommon;
};
// Specialization for SpecialType.
template<>
struct MyClass<SpecialType> : MyClassCommon<SpecialType> {
using MyClassCommon<SpecialType>::MyClassCommon;
SpecialType& foo();
};
用法是:
MyClass<int> a;
// a.foo(); // error: 'struct MyClass<int>' has no member named 'foo'
MyClass<SpecialType> b;
b.foo();