Explicit specialization of member function template in source file

心不动则不痛 提交于 2019-12-18 13:20:11

问题


I have a class with a member template function:

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

And in Writer's source file, I added explicit specializations for some_type:

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

This works... sometimes. Even if I definitely make sure that I have the right types:

writer.addField<some_type>("name", static_cast<int>(some_value));

Sometimes the explicit specialization gets called, and sometimes the primary gets called. What gives?


回答1:


Declaring specializations in a source file and can cause all sorts of subtle issues that are very difficult to diagnose. The compiler isn't obligated to help you in any regard here either. The standard strongly encourages you not to do this, with the help of a limerick, in [temp.expl.spec]/6-7:

If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined.

The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, [...], etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

It's likely that in some translation units, the specialization happened to be declared before the first use - and in some translation units it hasn't been. It's better to avoid all such issues entirely by simply declaring your specialization in your header:

// 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)
{ /* ... */ }

You can also just declare it in the header (no longer needs to be inline), and still define it in the source.



来源:https://stackoverflow.com/questions/30530364/explicit-specialization-of-member-function-template-in-source-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!