Я хочу создать оболочку вокруг std :: make_pair, которая принимает один аргумент и использует этот аргумент для создания первого и второго членов пары. Кроме того, я хочу воспользоваться семантикой перемещения.
Наивно, мы могли бы написать (игнорируя возвращаемые типы для ясности),
template <typename T>
void foo(T&& t)
{
std::make_pair(std::forward<T>(t),
std::forward<T>(t));
}
но вряд ли это сделает то, что мы хотим.
Мы хотим:
- В случае, когда foo вызывается с аргументом ссылки (const) lvalue, мы должны передать эту ссылку (const) в std :: make_pair без изменений для обоих аргументов.
- В случае, когда foo вызывается с аргументом ссылки rvalue, мы должны продублировать указанный объект, а затем вызвать std :: make_pair с исходной ссылкой rvalue, а также ссылкой rvalue на вновь созданный объект.
На данный момент я придумал:
template <typename T>
T forward_or_duplicate(T t)
{
return t;
}
template <typename T>
void foo(T&& t)
{
std::make_pair(std::forward<T>(t),
forward_or_duplicate<T>(t));
}
Но я разумно уверен, что это неправильно.
Итак, вопросы:
Это работает? Я подозреваю, что не в том, что если foo () вызывается со ссылкой на rvalue, тогда конструктор перемещения T (если он существует) будет вызываться при построении T, переданного по значению в forward_or_duplicate (), тем самым уничтожив t.
Даже если это сработает, оптимально ли это? Опять же, я подозреваю, что не в том, что конструктор копирования T будет вызываться при возврате t из forward_or_duplicate ().
Это похоже на обычную проблему. Есть идиоматическое решение?
std::make_pair(t, std::forward<T>(t))
, если бы порядок между оценками параметров был определен (к сожалению, это не так). - person Cameron   schedule 12.08.2015forward_or_duplicate
. - person T.C.   schedule 12.08.2015make_pair
принимает аргументы по ссылке, поэтому перемещение происходит внутри него, а копирование происходит до того, как вы введетеmake_pair
. - person T.C.   schedule 12.08.2015T
не выводится. Да, выглядит нормально. - person Kerrek SB   schedule 12.08.2015make_pair
, то то, что вы делаете, опасно. Порядок оценки не указан. Если класс идеально продвигается вперед, вы в безопасности, потому что привязка к ссылке ничего не делает, поэтому порядок не имеет значения: если вы берете что-либо по значению или берете что-либо по ссылке на другой тип, тогда вы будут возникать непредсказуемые и незаметные ошибки, которые трудно отследить, потому что порядок начинает иметь значение. - person Yakk - Adam Nevraumont   schedule 12.08.2015