5

我有一个看起来像这样的模板类:

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 真正生成显式特化,我需要在代码文件中放置一个正确类型的虚拟变量。

4

2 回答 2

8

除了 Martin York 的内联解决方案,您也可以在头文件中执行以下操作:

class D { };
template<> void C<D>::A(); // Don't implement here!

并提供一个带有实现的 .cpp 文件:

template<> void C<D>::A() { /* do code here */ }

因此,您可以通过提供单个定义来避免多个定义。这也有助于在发布库时将特定类型的实现隐藏在模板头文件之外。

于 2009-09-26T18:13:39.077 回答
5

尝试

template<> inline void c<int>::A() { ... }
//         ^^^^^^

正如您在头文件中定义的那样。每个看到它的源文件都将构建它的显式版本。这会导致您的链接错误。所以 jsut 将其声明为内联。

于 2009-09-26T17:25:34.497 回答