Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function template specialization in a namespace

I want to specialize a function template. This function is declared in a namespace:

namespace foo
{
   template <int>
   void function();
}

(For simplicity, the template is based on an int, whereas in my production code, it is an enum class, but it is the same issue. The same goes for a type based template)

Now I want to specialize it for a specific value:

template <>
void foo::function<0>()
{
}

This fails to compile with g++ -std=c++11 (versions 4.6, 4.7, 4.8 and 4.9):

specialization of ‘template void foo::function()’ in different namespace [-fpermissive]

clang++ -std=c++11 accepts this code.

g++ also accepts the following piece:

namespace foo
{
   template <>
   void function<0>()
   {
   }
}

Who's right, gcc or clang?

like image 902
stefan Avatar asked Jan 21 '15 15:01

stefan


1 Answers

According to the standard, §14.7.3/2, emphasis mine:

An explicit specialization shall be declared in a namespace enclosing the specialized template. An explicit specialization whose declarator-id is not qualified shall be declared in the nearest enclosing namespace of the template, or, if the namespace is inline (7.3.1), any namespace from its enclosing namespace set.

You have to put template<> function<0>(); in namespace foo. However, that rule only applies to an unqualified declarator-id. When you provide a qualified-id (as in foo::function<0>), I believe that clause should not apply, which makes clang correct here.

For example, given the function declared the question, I would expect the following:

namespace foo {
    template <> void function<0>(); // valid: unqualified explicit specialization
                                    // in the nearest enclosing namespace of the 
                                    // template
}

namespace bar {
    template <> void function<1>(); // invalid: unqualified explicit specialization
                                    // in the wrong namespace
}

struct baz {
    template <> void function<2>(); // invalid: unqualified explicit specialization
                                    // not in namespace scope
};

template <> void foo::function<3>(); // valid: qualified explicit specialization
                                     // is in a namespace, and id is qualified

template <> void bar::function<4>(); // invalid: there is no bar::function
                                     // to specialize
like image 150
Barry Avatar answered Oct 01 '22 22:10

Barry