源文件中成员函数模板的显式特化

Bar*_*rry 10 c++ templates explicit-specialization

我有一个具有成员模板功能的类:

// writer.h
class Writer {
public:
    ...
    template <typename T, typename V>
    void addField(const std::string& name, V v) 
    {
        // write something
    }
};
Run Code Online (Sandbox Code Playgroud)

在Writer的源文件中,我添加了明确的特化some_type:

// writer.cpp
template <>
void Writer::addField<some_type, int>(const std::string& name, int v)
{
    // specific some_type writing logic
}
Run Code Online (Sandbox Code Playgroud)

这有效......有时候.即使我确定我有合适的类型:

writer.addField<some_type>("name", static_cast<int>(some_value));
Run Code Online (Sandbox Code Playgroud)

有时会调用显式特化,有时会调用主要特征.是什么赋予了?

Bar*_*rry 12

在源文件中声明特化并可能导致各种难以诊断的细微问题.编译器也没有义务在这里帮助您.该标准强烈建议你不要在[temp.expl.spec]/6-7的利默里克的帮助下这样做:

如果模板,成员模板或类模板的成员是显式专用的,则应在首次使用该特化之前声明该特化,这将导致发生隐式实例化,在发生此类使用的每个翻译单元中; 无需诊断.如果程序没有提供显式特化的定义,并且特殊化的使用方式会导致隐式实例化或成员是虚拟成员函数,则程序格式错误,无需诊断.永远不会为已声明但未定义的显式特化生成隐式实例化.

函数模板,类模板,变量模板,类模板的成员函数等的显式特化声明的放置可以根据显式特化声明的相对位置来影响程序是否格式正确.以及在上文和下文中指定的翻译单元中的实例化点.写专业时,要注意它的位置; 或者使它编纂将是一种试图点燃其自焚的试验.

很可能在某些翻译单元中,专业化恰好在第一次使用之前被宣布 - 而在某些翻译单元中则没有.最好通过简单地声明标题中的专业化来完全避免所有这些问题:

// writer.h
class Writer {
public:
    ...
    template <typename T, typename V>
    void addField(const std::string& name, V v) 
    { /* ... */ }
};

// still writer.h
template <>
inline void Writer::addField<some_type, int>(const std::string& name, int v)
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)

您也可以在标题中声明它(不再需要内联),并且仍然在源中定义它.

  • 如果它在标题中,你需要使它成为"内联"; 或者,您可以*声明*标题中的特化,并在其他地方*定义*. (8认同)