& quot; Явная специализация std :: iterator_traits & lt; char * & gt; после создания экземпляра & quot; (Звон)

У меня есть некоторый код, который прекрасно компилируется под MSVC (или, так сказать, разработчиками Windows, которые мне его прислали), но выдает ошибку под CLang. Посмотрев вокруг, я обнаружил, что CLang действительно более строг в разрешении специализаций шаблонов, но я не уверен, куда мне поместить специализации в моем случае. В основном один из моих файлов имеет такую ​​структуру:

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;
};

Это в пределах namespace std блок. Сообщение об ошибке:

Explicit specialization of 'std::iterator_traits<char *>' after instantiation

Другая часть того же самого сообщения об ошибке (просматриваемое «расширением» сообщения об ошибке в XCode) говорит Implicit instantiation first required hereи нажав на это приводит меня к stl_iterator.hконкретно эта строка (строка 642):

typedef typename iterator_traits<_Iterator>::iterator_category
iterator_category;

Кто-нибудь знает, что делать в этом случае правильно? Я видел примеры с участием классов, но ни разу с использованием структуры.

1

Решение

Компилятор жалуется, что вы пытаетесь специализировать шаблон после создания экземпляра универсального шаблона — к этому моменту компилятор уже использовал универсальный шаблон для создания экземпляра, и он не может вернуться и использовать вашу специализацию вместо этого , Другими словами, что-то вроде этого:

template <typename T>
struct X
{
// Generic implementation
};

// Instantiate template by using it in any way
X<int> foo;

template<>
struct X<int>
{
// Specialization implementation for int
};

Исправление заключается в определении специализации до он создан, поэтому в этом примере вы переместите X<int> специализация до где раньше X<int> используется.

Обратите внимание, что STL уже определяет специализации std::iterator_trait для типов указателей, поэтому нет необходимости определять свою собственную специализацию здесь для char*, Обычно вы делаете это только для пользовательских типов итераторов, которые не являются указателями. См. § 24.3.1 / 2 стандарта C ++ 03:

[Шаблон iterator_traits<Iterator>] специализируется на указателях как

template<class T> struct iterator_traits<T*> {
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef random_access_iterator_tag iterator_category;
};

и для указателей на const как

template<class T> struct iterator_traits<const T*> {
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef const T* pointer;
typedef const T& reference;
typedef random_access_iterator_tag iterator_category;
};

Так что нет смысла предоставлять свои собственные std::iterator_traits<char*> специализация. поскольку char* это не определенный пользователем тип, это также неопределенное поведение в соответствии со стандартом. §17.4.3.1 / 1 говорит:

Для программы на C ++ добавление объявлений или определений в пространство имен std или namespace не определено.
в пространстве имен std если не указано иное. Программа может добавить шаблон специализации для любого
стандартный шаблон библиотеки для пространства имен std, Такая специализация (полная или частичная) стандарта
шаблон библиотеки приводит к неопределенному поведению, если объявление не зависит от определенного пользователем имени
внешняя связь и если специализация не соответствует стандартным требованиям библиотеки для исходного шаблона.163)

163) Любой библиотечный код, который создает экземпляры других библиотечных шаблонов, должен быть подготовлен для адекватной работы с любой предоставленной пользователем специализацией.
соответствует минимальным требованиям стандарта

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]