如何只为C++模板类中的一个方法提供显式特化?

BCS*_*BCS 5 c++ templates explicit-specialization

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

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 */ }
Run Code Online (Sandbox Code Playgroud)

我想要的是仅A在保留默认值B和"其他内容"时提供显式特化.

到目前为止我尝试过的是

class D { };
template<> void C<D>::A() { /*...*/ } // Gives a link error: multiple definition
Run Code Online (Sandbox Code Playgroud)

我尝试过的每个其他变体都会因解析错误而失败.


我做了什么:

最初的问题是显式特化是在头文件中,因此它被转储到几个目标文件中并弄乱了链接(为什么链接器没有注意到符号的所有实例都是相同的只是闭嘴?)

解决方案最终是将显式特化从头文件移动到代码文件.但是为了使头文件的其他用户不是默认版本的实例,我需要将原型放回头部.然后为了让GCC实际生成显式特化,我需要在代码文件中放置一个正确类型的虚拟变量.

mmm*_*mmm 8

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

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

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

template<> void C<D>::A() { /* do code here */ }
Run Code Online (Sandbox Code Playgroud)

因此,您可以通过提供单个定义来避免多个定义.在发布库时,这也可以隐藏特定类型的实现,使其远离模板头文件.


Mar*_*ork 5

尝试

template<> inline void c<int>::A() { ... }
//         ^^^^^^
Run Code Online (Sandbox Code Playgroud)

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

  • @BCS:`template`和`inline`是正交的.(但是,虽然这可能会隐藏错误,但根本不会修复它.) (2认同)