Por que usar std :: forward nos conceitos?

Eu estava lendo opágina cppreference em Restrições e notei este exemplo:

// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
    swap(std::forward<T>(t), std::forward<U>(u));
    swap(std::forward<U>(u), std::forward<T>(t));
};

Estou confuso por que eles estão usandostd::forward. Alguma tentativa de suportar tipos de referência nos parâmetros do modelo? Não queremos ligarswap com lvalues, e oforward expressões sejam rvalues quandoT eU são tipos escalares (sem referência)?

Por exemplo, eu esperaria que este programa falhasse, dada a suaSwappable implementação:

#include <utility>

// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
    swap(std::forward<T>(t), std::forward<U>(u));
    swap(std::forward<U>(u), std::forward<T>(t));
};

class MyType {};
void swap(MyType&, MyType&) {}

void f(Swappable& x) {}

int main()
{
    MyType x;
    f(x);
}

Infelizmente o g ++ 7.1.0 me dá umaerro interno do compilador, o que não lança muita luz sobre isso.

Aqui ambosT eU deveria estarMyTypeestd::forward<T>(t) deve retornarMyType&&, que não pode ser passado para o meuswap função.

Esta implementação deSwappable errado? Perdi alguma coisa?

questionAnswers(2)

yourAnswerToTheQuestion