我有一个模板类,看起来像这样:
template<class T> class C
{
void A();
void B();
// Other stuff
};
template<class T> void C<T>::A() { /* something */ }
template<class T> void C<T>::B() { /* something */ }
我想要的是仅保留A
的显式专精,同时保留B
和“其他内容”的默认值。
到目前为止我尝试过的是
class D { };
template<> void C<D>::A() { /*...*/ } // Gives a link error: multiple definition
我尝试过的每个其他变体都会因解析错误而失败。
最初的问题是显式特化是在头文件中,所以它被转储到几个目标文件中并弄乱链接(为什么链接器没有注意到符号的所有实例都是相同的只是关闭吗?)
解决方案最终是将显式特化从头文件移动到代码文件。但是为了使头文件的其他用户不是默认版本的实例,我需要将原型放回头部。然后为了让GCC实际生成显式特化,我需要在代码文件中放置一个正确类型的虚拟变量。
答案 0 :(得分:8)
除了Martin York的内联解决方案,您也可以在头文件中执行:
class D { };
template<> void C<D>::A(); // Don't implement here!
并提供带有实现的.cpp文件:
template<> void C<D>::A() { /* do code here */ }
因此,您可以通过提供单个定义来避免多个定义。 在发布库时,这也可以将特定类型的实现隐藏在远离模板头文件的位置。
答案 1 :(得分:5)
尝试
template<> inline void c<int>::A() { ... }
// ^^^^^^
正如您在头文件中定义的那样。 每个看到它的源文件都会构建它的显式版本。这导致您的链接错误。所以jsut将其声明为内联。