std :: iterator_traits для целочисленных типов в стандартной библиотеке Microsoft

У меня есть функция шаблона, которая должна быть специализированной для итераторов. Итак, что я сделал по принципу:

template <typename T>
void function2(T whatever, typename std::iterator_traits<T>::pointer) // ... iterator

template <typename T>
void function2(T whatever, ...) // ... non-iterator

template <typename T>
void function(T whatever) {
function2(whatever, NULL);
}

И я врезался в стену, потому что стандартная библиотека Microsoft специализируется std::iterator_traits для всех числовых типов (bool, char, int, float…). И делает это так, чтобы reference а также pointer не являютсяvoidнесмотря на то, что ни operator* ни operator-> можно назвать по этим типам.

Хорошо, я могу проверить std::iterator_traits<T>::category производный std::input_iterator (на самом деле я думаю, std::forward_iterator более уместно в моем случае) за счет некоторого более сложного шаблонного механизма.

Однако мне было бы интересно узнать:

  • Почему они определяют iterator_traits для типов, которые не соответствуют концепции итератора (даже для выходных итераторов требуется как минимум одинарный operator*Ни один из этих типов не имеет ни одного.
  • Они нарушают спецификацию C ++ при этом? Не то чтобы Microsoft не нарушала это повсеместно, но если бы они были такими, я был бы доволен обходным решением для конкретного компилятора, если бы они этого явно не сделали.
  • И вообще это вообще работоспособно? Похоже, std::iterator_traits<T>::pointer всегда существует, но не определено, и это приводит к ошибке, а не к SFINAE.

1

Решение

Другие функции [res.on.functions]

[…]

2 В частности, эффекты не определены в следующих случаях:

  • для типов, используемых в качестве аргументов шаблона при создании экземпляра компонента шаблона, если операции над
    тип не реализует семантику применимого подпункта Требования

Для того, чтобы использовать iterator_traits<T>, T должен быть итератором. Если это не так, поведение не определено. Вы не можете определить, является ли тип T является итератором во время компиляции. Это даже теоретически невозможно, так как типу разрешено поддерживать те же операторы и определения типов, что и итераторам, так что общий тип реализации iterator_traits<T> может быть создан без каких-либо ошибок или предупреждений, но с совершенно другим значением.

Подумав об этом, так как ваш комментарий уточняет, что разумное предположение достаточно хорошо, я думаю, что вам лучше использовать SFINAE и enable_if обнаружить основные операции (унарный * и префикс ++), с помощью std::iterator_traits<T>::pointer только если эти условия соблюдены.

2

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

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

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