2016-10-19 4 views
2

Я пытаюсь выяснить, как скомпилировать следующий код без предупреждения/ошибки.std :: sort на пару, у которой у 2-го элемента нет компаратора

Это часть кода, которую я вижу в проекте, над которым я работаю в офисе. (Имя переменного/класса было изменено)

vector<pair<time_t, ClassA *> > vec = getVecFromSomewhere(); 
std::sort(vec.begin(), vec.end());  

Я проверил исходный код ClassA, который я не вижу какой-либо компаратор реализуется. Так верно ли, что только первый элемент пары требует компаратора?

Редактировать: все экземпляры ClassA происходят из одного и того же вектора.

+0

Это 'ClassA *' не 'ClassA', вы сортируете указатель не значение. – Holt

+2

[Эта ссылка на оператор сравнения std :: pair] (http://en.cppreference.com/w/cpp/utility/pair/operator_cmp) может быть полезна. –

ответ

5

ClassA может не иметь operator<, но это не имеет значения, потому что вы храните ClassA* в вашей паре, не ClassA. You может сравнить указатели, поэтому ваш код работает.

ClassA as [10]; 
as[0] < as[1]; //invalid, compares ClassAs 
as < as+1; //valid, compares ClassA*s 

Обратите внимание, что вам нужно быть очень осторожным с семантикой вашего сравнения. Вы действительно хотите сравнивать эти указатели? Они указывают на один и тот же объект массива? Если нет, вы можете отправиться в забавную страну неопределенного поведения, как только вы их сравните. Если это так, это упорядочение может все еще быть не тем, кого вы хотите.

+0

О, это имеет смысл. thanks =) – Mox

+1

Небольшое добавление может быть в порядке: вы можете использовать относительное сравнение (меньше, больше) для * связанных * указателей (например, для вашего примера массива). В противном случае определяется только равенство/неравенство. –

+1

@JoachimPileborg: Но вы можете использовать 'std :: less (ptr1, ptr2)' для несвязанных указателей - OP может захотеть написать функцию сравнения, которая делает это. –

3

Ваше понимание неверное. std::pair определяет operator<. Он сравнивает лексикографически, т. Е. Второй элемент сравнивается только в том случае, если первые равны.

Точная standardese (n4606):

template <class T1, class T2>

constexpr bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y)

Возвращает: x.first < y.first || (!(y.first < x.first) && x.second < y.second).

Этот случай является немного особенным, потому что невозможно определить указатели на объекты, которые не являются частями одного и того же объекта/массива.

+0

Вы имеете в виду, что поведение здесь не определено? – Mox

+0

@Mox не может сказать. Все указатели «ClassA *» указывают на один и тот же массив? – krzaq

+0

@Mox: Поведение почти наверняка непреднамеренно, даже если оно будет формально определено. – MSalters

Смежные вопросы