Почему данный код бросает исключение Invalid comparator
#include <iostream>
#include <algorithm>
class StrCmp
{
public:
template <typename T> bool operator()
(const T* p1, const T* p2) const
{
while (*p1 && *p2 && *p1 == *p2)
++p1, ++p2;
return *p2 - *p1 > 0;
}
};
int main(int argc, char* argv[] )
{
const unsigned int* a[]
{
(const unsigned int*)"Сидоров",
(const unsigned int*)"Петров",
(const unsigned int*)"Иванов",
(const unsigned int*)"Аров",
(const unsigned int*)"Аро",
(const unsigned int*)"",
};
std::sort(a, a + 6, StrCmp() );
return 0;
}
В данном случае все просто - у вас сравниваются беззнаковые величины, и *p2 - *p1 всегда больше нуля. По беззнаковости :)
А Visual C++ в отладочном режиме проверяет компаратор, сравнивая два вызова - типа comp(a,b) и comp(b,a), и если они оба оказываются истинны - он справедливо полагает компаратор некорректным.
Ибо не может одновременно быть a < b и b < a. Исправьте свой компаратор, чтобы он давал правильные результаты...
P.S. Выполните такой код:
std::cout << StrCmp()(a[2],a[5]) << std::endl;
std::cout << StrCmp()(a[5],a[2]) << std::endl;
Вывод будет - две единицы. Т.е. и a[2] < a[5], и a[5] < a[2] - так говорит ваш компаратор.
Но так не бывает, и VC++ (в отладочном режиме) сообщает вам о том, что ваш компаратор никуда не годится. Потому что сравнение a с b дает тот же результат, что и b с a...
При переинтерпретации обыкноенной строки char [] с единственным \0 в конце как массива unsigned int [] нет практически никаких шансов на то, что в конце такого массива unsigned int [] вы увидите завершающий 0. То есть если ваш цикл сравнения не найдет различий, то такой цикл не будет останавливаться в конце строки, а будет выходить за пределы доступной памяти и сравнивать неинициализированные и/или нестабильные значения. Сравнение нестабильных значений ведет к нестабильным и/или несогласованным результатам сравнения, что ведет к неопределенному поведению, в т.ч. выбросу такого исключения.
Переинтерпретация памяти - это почти всегда грязный хак. Но если уж вы хотите сравнивать ваши строки именно так, то вам надо гарантировать, что в конце каждой строки будет присутствовать нулевое значение типа unsigned int. Например, при sizeof(unsigned int) == 4 ваши строки должны выглядеть как
const unsigned int* a[]
{
(const unsigned int*)"Сидоров\0\0\0\0\0\0",
(const unsigned int*)"Петров\0\0\0\0\0\0",
(const unsigned int*)"Иванов\0\0\0\0\0\0",
(const unsigned int*)"Аров\0\0\0\0\0\0",
(const unsigned int*)"Аро\0\0\0\0\0\0",
(const unsigned int*)"\0\0\0\0\0\0",
};
Т.е. в общем случае (не подстраиваясь под длину конкретной строки) вам нужно как минимум 7 нулей в конце строки, чтобы гарантировать, что переинтерпретация этой строки как unsigned int [] обязательно найдет в конце нулевое значение.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники