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 ).
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With