20 Library introduction [library]

20.5 Library-wide requirements [requirements]

20.5.3 Requirements on types and expressions [utility.requirements]

20.5.3.2 Swappable requirements [swappable.requirements]

В этом подпункте приведены определения заменяемых типов и выражений. В этих определениях let t обозначает выражение типа T, а let u обозначает выражение типа U.

Объект t является swappable with объектом u тогда и только тогда, когда:

  • выражения swap(t, u) и swap(u, t) действительны при оценке в контексте, описанном ниже, и

  • эти выражения имеют следующие эффекты:

    • объект, на который ссылается, t имеет ценность, первоначально принадлежащую u и

    • объект, на который ссылается, u имеет первоначальное значение t.

Контекст , в котором swap(t, u) и swap(u, t) оцениваются должен гарантировать , что бинарная функция не-член с именем «своп» выбирается с помощью overload resolution по набору кандидатов , который включает в себя:

[ Note: Если T и U являются как фундаментальными типами, так и массивами фундаментальных типов и объявления из заголовка <utility> находятся в области видимости, общий поисковый набор, описанный выше, эквивалентен поиску по квалифицированному имени, применяемому к выражению std​::​swap(t, u) или по std​::​swap(u, t) мере необходимости. ] end note

[ Note: Не указано, включает ли компонент библиотеки, требующий замены, заголовок, <utility> чтобы гарантировать соответствующий контекст оценки. ] end note

Rvalue или lvalue t есть swappable тогда и только тогда, когда их t можно заменить любым rvalue или lvalue, соответственно, типа T.

Тип X удовлетворяющего любой из iterator requirements удовлетворяют требования , ValueSwappable если для любого объекта разыменовываемого x типа X, *x является заменой.

[ Example: Код пользователя может гарантировать, что оценка swap вызовов выполняется в соответствующем контексте при различных следующих условиях:

#include <utility>

// Requires: std​::​forward<T>(t) shall be swappable with std​::​forward<U>(u).
template <class T, class U>
void value_swap(T&& t, U&& u) {
  using std::swap;
  swap(std::forward<T>(t), std::forward<U>(u)); // OK: uses “swappable with” conditions
                                                // for rvalues and lvalues
}

// Requires: lvalues of T shall be swappable.
template <class T>
void lv_swap(T& t1, T& t2) {
  using std::swap;
  swap(t1, t2);                                 // OK: uses swappable conditions for
}                                               // lvalues of type T

namespace N {
  struct A { int m; };
  struct Proxy { A* a; };
  Proxy proxy(A& a) { return Proxy{ &a }; }

  void swap(A& x, Proxy p) {
    std::swap(x.m, p.a->m);                     // OK: uses context equivalent to swappable
                                                // conditions for fundamental types
  }
  void swap(Proxy p, A& x) { swap(x, p); }      // satisfy symmetry constraint
}

int main() {
  int i = 1, j = 2;
  lv_swap(i, j);
  assert(i == 2 && j == 1);

  N::A a1 = { 5 }, a2 = { -5 };
  value_swap(a1, proxy(a2));
  assert(a1.m == -5 && a2.m == 5);
}

end example]