Is `char * p = 0; std:: equal (p, p, p) `четко определен в соответствии со стандартом С++?
Является ли следующее определение корректным в соответствии со стандартом С++?
char* p = 0;
std::equal(p, p, p);
Вопрос в самом деле:
Требуется ли стандарт, чтобы std::equal(begin1, end1, begin2)
реализовывался таким образом, что если begin1 == end1
, то begin1
и begin2
может быть любым указателем, даже тем, который не указывает на действительный объект памяти?
Я предполагаю, что это намерение стандарта, но я не смог найти утверждение, которое делает это ясным.
Причина, по которой я беспокоюсь об этом, заключается в том, что VisualStudio, по-видимому, пытается проверить "достоверность" begin2
даже при begin1 == end1
. И это противоречит моему пониманию требований стандарта.
EDIT: Вот код от VS 2012, который, я считаю, нарушает стандарт:
template<class _InIt1, class _InIt2> inline
bool equal(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2)
{ // compare [_First1, _Last1) to [First2, ...)
_DEBUG_RANGE(_First1, _Last1);
_DEBUG_POINTER(_First2);
return (_Equal1(_Unchecked(_First1), _Unchecked(_Last1), _First2, _Is_checked(_First2)));
}
template<class _Ty> inline
void _Debug_pointer(const _Ty *_First, _Dbfile_t _File, _Dbline_t _Line)
{ // test iterator for non-singularity, const pointers
if (_First == 0)
_DEBUG_ERROR2("invalid null pointer", _File, _Line);
}
Ответы
Ответ 1
Итак, у нас есть 25.2.1/1, который гласит:
Возвращает: true, если для каждого итератора я в диапазоне [first1, last1) следуя соответствующим условиям: * я == * (first2 + (i - first1)), pred (* i, * (first2 + (i - first1)))!= false.
В противном случае, возвращает false.
В вашем случае нет итераторов в диапазоне [0, 0), поэтому "каждый" итератор в диапазоне проходит тест, но фактический тест не должен выполняться (поскольку в пробеге не существует итераторов).
Он выглядит как ошибка VisualStudio для меня.
Ответ 2
Как отметил @Zac, эта проверка является Visual Studio, являющейся дополнительным педантичным именем безопасности. Если вы хотите, чтобы Visual Studio более точно соответствовала стандарту даже в сборках отладки, вы можете отключить это поведение, установив макрос _ ITERATOR_DEBUG_LEVEL в 0.
Ответ 3
С вашим обновлением ясно, что это не нарушение стандарта, а проверка отладки. Если вы скомпилируете его в режиме Release, эти проверки не запускаются, а функция соответствует стандартным описаниям.
Полезно иметь эту информацию в режиме отладки, так как это поможет вам отследить некоторые трудно найти ошибки.
Ответ 4
Стандартные состояния С++ 11 "[i, i) - пустой диапазон" в 24.2.1/5.
Однако в 24.2.1/5 сначала подразумевается, что 0 должно быть сингулярным значением, а затем означает: "Результаты большинства выражений undefined для сингулярных значений". Затем он перечисляет исключения для поведения undefined, но сравнение не включено.
Так что, возможно, undefined сравнить сингулярные итераторы для равенства, поэтому сделать оценку [i, i) невозможно.
Это также указывает на то, что ваша ошибка во время выполнения происходит внутри функции с именем _Equal1().
Я думаю, что стандарт смутно по отношению к этому, и я совсем не уверен, что это ошибка в Visual Studio 2012.
http://cplusplus.github.io/LWG/lwg-unresolved.html в главе "1213. Значение допустимого и единственного итератора, ограниченного" также довольно забавно с этой путаницей...