Должна ли использоваться моя перегрузка swap? Это ошибка libstdc ++ (GCC)? - PullRequest
2 голосов
/ 02 марта 2012

Рассмотрим следующий код:

#include <algorithm>
#include <iostream>
#include <vector>

struct A {
   int val;

   bool operator<(const A& other) const {
      std::cout << "operator\n";
      return val < other.val;
   }
};

void swap(A& a, A& b) {
   std::cout << "foo\n";
   std::swap(a.val, b.val);
}

int main()
{
   std::vector<A> a(2);
   a[0].val = 10;
   a[1].val = -1;

   std::sort(a.begin(), a.end());
}

C ++ 11's std::sort помещает ValueSwappable требования к аргументам итератора, семантике перемещения и ничего больше, подразумевая, что std::sort "гарантированно" выполнит обмен, если элементы должны быть перемещены , И 17.6.3.2/3 предполагает, что моя перегрузка определенно должна быть выбрана в этом случае.

  • Это правильно?

clang 3.1 SVN libc ++ выбирает мой swap (то есть я вижу "foo"); Libstdc ++ GCC 4.6.3 не поддерживает.

  • Это ошибка GCC (при условии, что моя стандартная интерпретация верна)? Или я что-то упустил?

Ответы [ 2 ]

6 голосов
/ 03 марта 2012

Я публикую это как ответ, потому что у меня нет репутации, чтобы комментировать.

Как указал @FredOverflow, libstdc ++ использует конструкторы перемещения и операторы присваивания при сортировке.Тем не менее, мне кажется странным, что он не использует ADL для кода до c ++ 11, поэтому люди могут подключать оптимизированные функции подкачки.

6 голосов
/ 02 марта 2012

C ++ 11 * std::sort устанавливает ValueSwappable требования к аргументам итератора, семантике перемещения и ничего больше, подразумевает, что std::sort "гарантированно" выполнит обмен, если элементы должны перемещаться вокруг .

Я не вижу этой гарантии. Кто сказал, что std::sort не может использовать семантику перемещения вместо свопов? Фактически, после просмотра стандарта для дословной спецификации, я считаю, что именно это и происходит:

Требуется: RandomAccessIterator должен удовлетворять требованиям ValueSwappable (17.6.3.2). Тип *first должен удовлетворять требованиям MoveConstructible (таблица 20) и MoveAssignable (таблица 22).

Обратите внимание, что итераторы должны быть ValueSwappable, а не элементами, на которые они указывают.

...