Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit specialization of member function template in source file

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?

like image 490
Barry Avatar asked May 29 '15 13:05

Barry


People also ask

What is the syntax for explicit class specialization?

What is the syntax to use explicit class specialization? Explanation: The class specialization is creation of explicit specialization of a generic class. We have to use template<> constructor for this to work. It works in the same way as with explicit function specialization.

What is function template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

What is the specialty of a template function give example?

Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.

Can member functions be declared as template?

The term member template refers to both member function templates and nested class templates. Member function templates are function templates that are members of a class or class template. Member functions can be function templates in several contexts.


1 Answers

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.

like image 175
Barry Avatar answered Sep 20 '22 19:09

Barry