¿Por qué usar std :: forward en conceptos?

Estaba leyendo elPágina de preferencias sobre restricciones y noté este ejemplo:

// 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));
};

Estoy confundido por qué están usandostd::forward. ¿Algún intento de admitir tipos de referencia en los parámetros de la plantilla? No queremos llamarswap con valores, y no sería elforward las expresiones sean valores cuandoT yU son tipos escalares (sin referencia)?

Por ejemplo, esperaría que este programa fallara dado suSwappable implementación:

#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);
}

Lamentablemente, g ++ 7.1.0 me da unerror interno del compilador, que no arroja mucha luz sobre esto.

Aquí los dosT yU debiera serMyTypeystd::forward<T>(t) debería volverMyType&&, que no se puede pasar a miswap función.

¿Es esta implementación deSwappable ¿incorrecto? ¿Me he perdido algo?

Respuestas a la pregunta(2)

Su respuesta a la pregunta