【问题标题】:How to specialize a non-inline templated member function ? (for use in different translation units)如何专门化非内联模板化成员函数? (用于不同的翻译单元)
【发布时间】:2012-01-10 12:59:09
【问题描述】:

上下文

我们开发了一个模板化设置系统类,它将成为我们向不同架构的用户公开的 API 的一部分(少说:我们不应该依赖编译器特定的行为)

通用代码如下所示:

在标题中

namespace Firm
{

// Class definition
class A
{
  template<class T>
  void foo(T* aParam);
};

// Non specialized template definition
template<class T>
void A::foo(T* aParam)
{
  //...
}

// Declaration of a specialization
template<>
void A::foo<int>(int* aParam); 

} // namespace

在 CPP 文件中

namespace Firm
{

// Definition of the specialized member function
template<>
void A::foo<int>(int* aParam)
{
  //...
}

} // namespace


问题

gcc 4.x 一切正常。 (即不同的编译单元在适当的时候使用专门的方法。)但是我读到以下条目后感到不舒服:

Visibility of template specialization of C++ function

接受的答案状态,如果我理解正确,如果 从调用中看不到模板方法的特化定义,则这是一个错误网站。 (所有不是上面列出的CPP文件但包含头文件的编译单元都是这种情况)

  1. 我不明白为什么此时声明还不够(标题提供的声明)?

  2. 如果它真的是一个错误,有没有正确的方法来定义它的专业化:

    • 非内联
    • 可用于包含标头(以及与相应 .obj 的链接)的任何编译单元?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    将声明放在头文件中。

    编译器要么需要实例化模板(需要定义),要么你需要使用 c++0x 外部模板

    看这里:https://stackoverflow.com/a/8131212/258418

    编辑 @ 单定义规则: 你应该没问题,因为我体验了模板的以下行为: 在不同的 o 文件中创建它们(多次,由于多次编译而耗时),当链接器进入时,它会删除重复项并使用一个实例化。

    另请查看此答案/wiki 链接:https://stackoverflow.com/a/8133000/258418

    edit2

    对于类它的工作方式如下:

    extern template class yourTemplate<int>; //tell the compiler to just use this like a funciton stub and do no instantiation. put this in the header
    
    template class yourTemplate<int>; //instantiation, put this in a c file/object that you link with the project
    

    对于您的功能,它应该像这样工作: // 在你的头文件中声明一个特化 外部模板 无效 A::foo(int* aParam);

    //in your cpp file
    template<>
    void A::foo<int>(int* aParam) {
        code...
    }
    
    template class A::foo<int>(int* aParam);
    

    【讨论】:

    • 如果方法不是内联的,这违反了单一定义规则。 (当答案只有第一行时发布)
    • 为什么需要为特殊情况实例化模板,因为标题说“我声明模板的完整特殊化存在于 int”。这种特化可以恕我直言,其行为类似于任何常规方法,并且链接器将负责检查该方法的一个且仅一个定义存在。
    • 我认为您在完全指定的模板(您提供的链接指的是:stackoverflow.com/a/8133000/258418)和模板的完全专业化(我的问题主要是关于什么)之间混淆了。当您陷入模板的完全指定用法与该模板的已定义完整专业化匹配的情况时,我认为无需实例化模板。
    • 试试这个:extern template&lt;&gt; SomeFunc&lt;int&gt;(); 让编译器知道你有特化,所以它不会实例化非特化版本并在源文件(.cpp)中显式实例化它。或者如我所说,将专业化的定义放在标题中。后者的缺点是,每次在不同的编译单元中使用它时,你都会为你的专业化重新编译代码(链接器稍后会对此进行排序),专业的部分是,如果你的专业化从未使用过,那就永远不会实例化(显式实例化就是这种情况)。
    • 第二种的另一个缺点是它会违反“单一定义规则”。 (刚刚使用 VS 2010 和 gcc 进行了测试)如果编译器必须制作多个,链接器会整理出用于相同完整规范的模板实例化。但是再一次,当涉及到模板方法的完全专用版本时,不会发生实例化(因为具体代码已经存在,所以你写了)
    猜你喜欢
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多