Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

warning: specialization of template in different namespace

Tags:

c++

With the following piece of code I get the warning:

warning: specialization of ‘template<class _Iterator> struct std::iterator_traits’ in different namespace [-fpermissive]

template<> class std::iterator_traits<Token_ptr>{
public:
    typedef Word difference_type;
    typedef Word value_type;
    typedef Token_ptr pointer;
    typedef Word& reference ;
    typedef std::bidirectional_iterator_tag iterator_category ;
};

While everything works correctly, does any body know what exactly means and why is issued the warning. ( g++ issues the warning while clang++ doesn't ).

like image 574
George Kourtis Avatar asked Aug 31 '14 17:08

George Kourtis


2 Answers

There is one visible problem here, and one potentially invisible problem. The visible problem is that this code is not in a namespace std block. To specialize a template, you need to be within the namespace of the template you are specializing. Providing the namespace name as part of the type doesn't actually work in this case. So you need to do this:

namespace std
{
    template<> class iterator_traits<Token_ptr>{
    public:
        typedef Word difference_type;
        typedef Word value_type;
        typedef Token_ptr pointer;
        typedef Word& reference ;
        typedef std::bidirectional_iterator_tag iterator_category ;
    };
}

The other potential problem is that this code may already be inside of another namespace block (I can't tell because this is presumably not the entire source file). If it is, you need to close that namespace block first so that namespace std is not nested within any other namespace blocks.

Further reading: Specialization of 'template<class _Tp> struct std::less' in different namespace

like image 116
cdhowie Avatar answered Oct 14 '22 03:10

cdhowie


Assuming that you are compiling this in C++11 mode (since clang gave no warning) and that this specialization is in the global namespace, then there's nothing wrong with your code. It's a g++ bug. §14.7.3 [temp.expl.spec]/p2:

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. Such a declaration may also be a definition. If the declaration is not a definition, the specialization may be defined later (7.3.1.2).

The global namespace is a "namespace enclosing the specialized template", and your declarator-id is qualified with std::, so the second sentence doesn't apply. As a workaround, you can do what cdhowie's answer suggests - i.e., opening a namespace std block and putting the specialization there.

See CWG issue 374 and GCC bug 56480.

like image 42
T.C. Avatar answered Oct 14 '22 04:10

T.C.