Ответ 1
Прежде всего, прочитайте это, чтобы получить полное представление о пересылке. (Да, я передаю большую часть этого ответа в другом месте.)
Подводя итог, пересылка означает, что lvalues остаются lvalues и rvalues остаются rvalues. Вы не можете сделать это с помощью одного типа, так что вам нужно два. Поэтому для каждого пересылаемого аргумента вам нужны две версии для этого аргумента, для которых требуется 2 N комбинации для функции. Вы можете кодировать все комбинации функции, но если вы используете шаблоны, тогда эти различные комбинации генерируются для вас по мере необходимости.
Если вы пытаетесь оптимизировать копии и перемещения, например:
struct foo
{
foo(const T& pX, const U& pY, const V& pZ) :
x(pX),
y(pY),
z(pZ)
{}
foo(T&& pX, const U& pY, const V& pZ) :
x(std::move(pX)),
y(pY),
z(pZ)
{}
// etc.? :(
T x;
U y;
V z;
};
Затем вы должны остановиться и сделать это следующим образом:
struct foo
{
// these are either copy-constructed or move-constructed,
// but after that they're all yours to move to wherever
// (that is, either: copy->move, or move->move)
foo(T pX, U pY, V pZ) :
x(std::move(pX)),
y(std::move(pY)),
z(std::move(pZ))
{}
T x;
U y;
V z;
};
Вам нужен только один конструктор. Руководство: если вам нужна ваша собственная копия данных, сделайте эту копию в списке параметров; это позволяет решить скопировать или перейти к вызывающему и компилятору.