I’ve got some code that compiles fine under MSVC (or so say the Windows developers who sent me it), but gives an error under CLang. Having looked around I’ve found that CLang is indeed more strict about resolving template specializations, but I’m not sure where I should put the specializations in my case. Basically one of my files has a struct like this:
template<>
struct iterator_traits< char * > // error is here
{
typedef random_access_iterator_tag iterator_category;
typedef char value_type;
typedef ptrdiff_t difference_type;
typedef difference_type distance_type;
typedef char * pointer;
typedef char & reference;
};
This is within a namespace std block. The error message is:
Explicit specialization of 'std::iterator_traits<char *>' after instantiation
Another part of the same error message (viewed by ‘expanding’ the error message in Xcode) says Implicit instantiation first required here, and clicking on that takes me to stl_iterator.h, specifically this line (line 642):
typedef typename iterator_traits<_Iterator>::iterator_category
iterator_category;
Does anyone know what the correct thing to do would be in this case? I’ve seen examples involving classes but never one involving a struct.
The compiler is complaining that you’re trying to specialize a template after instantiating the generic template — by that point in time, the compiler has already used the generic template for the instantiation, and it can’t go back and use your specialization instead. In other words, something like this:
The fix is to define the specialization before it’s instantiated, so in this example, you’d move the
X<int>specialization to before whereX<int>is used.Note that the STL already defines specializations of
std::iterator_traitfor pointer types, so there’s no need to define your own specialization here forchar*. You’d typically only do that for user-defined iterator types which are not pointers. See §24.3.1/2 of the C++03 standard:So there’s no point to providing your own
std::iterator_traits<char*>specialization. Sincechar*is not a user-defined type, it’s also undefined behavior according to the standard. §17.4.3.1/1 says: