2
votes

I'm specializing member functions of a template class in a header file like so:

#pragma once

#include <iostream>

template<class T>
struct Test
{
    void Print() { }
};

template<>
void Test<int>::Print()
{
    std::cout << "int" << std::endl;
}

Is it correct to put the specialization in a header file (without it being inline), or should it be in a cpp file? It compiles fine as shown above (using VS2012), but I'm rather surprised I don't get multiple definition linker errors.

2
I do get a linker error, if I include this code in two different files and actually use Test<int>::Print (using g++4.8.1).dyp
No linker error in VS2013. (Not even a warning or anything, even if the two definitions are different.)dyp

2 Answers

2
votes

The ODR requires exactly one definition for non-inline functions that are ODR-used (that roughy means, for functions, being potentially called).

Quoting n3485, [basic.def.odr]

4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

Then, there's an exception for templates (i.e. not for functions):

6 There can be more than one definition of a class type [...], class template, non-static function template, static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified in a program provided that [...]

[emphasis mine]

An explicit specialization of a template is not a template. For example, an explicitly specialized class template is a class (with a strange name). Therefore, your assumption is correct and multiple definitions for explicitly specialized members of class templates violate the ODR.

With g++4.8.1, I even get a linker error in such a program; note that I have ODR-used the function. No diagnostic is required for a violation of the ODR.

1
votes

Putting the specialisation in the header file is the canonical form (as boost does), it doesn't violate the ODR.