C++ - Define member function outside template-class but in header

前端 未结 1 1218
北荒
北荒 2021-01-15 00:30

I have defined a simple class-template with one member function. It is defined outside the class with an additional (explicit) specialization, also defined outside the class

1条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-15 01:26

    14.7/5 says

    5 For a given template and a given set of template-arguments,

    • an explicit instantiation definition shall appear at most once in a program,
    • an explicit specialization shall be defined at most once in a program (according to 3.2), and
    • both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless the explicit instantiation follows a declaration of the explicit specialization.

    An implementation is not required to diagnose a violation of this rule.

    The second bullet applies to your case. The ODR defined in 3.2 says the same thing, albeit in a less distilled form.

    Regardless of where and how the non-specialized version of member function is defined, the specialized version definition

    template <> bool TestClass::MemberFunction()
    {
        return true;
    };
    

    has to go into a .cpp file. If kept in the header file, it will produce an ODR violation once the header gets included into more than one translation unit. GCC reliably detect this violation. MSVC seems to be less reliable in that regard. But, as the quote above states, an implementation is not required to diagnose a violation of this rule.

    The header file should only contain a non-defining declaration of that specialization

    template <> bool TestClass::MemberFunction();
    

    The fact that in MSVC the error appears or disappears depending on such seemingly unrelated factor as how the non-specialized version of the function is defined must be a quirk of MSVC compiler.


    After further research, it appears that MSVC implementation is actually broken: its behavior goes beyond what's allowed by the "no diagnostic is required" permission given by the language specification.

    The behavior you observed in your experiments in consistent with the following: declaring the primary function template as inline automatically makes the explicit specialization of that template inline as well. This is not supposed to be that way. In 14.7.3/14 the language specification says

    An explicit specialization of a function template is inline only if it is declared with the inline specifier or defined as deleted, and independently of whether its function template is inline.

    0 讨论(0)
提交回复
热议问题