Двойная функция с C ++ 0x - PullRequest
       3

Двойная функция с C ++ 0x

1 голос
/ 24 августа 2011

Допустим, у меня есть следующий простой класс Vector:

template <class N>
class Vector<N>
{
public:
  std::array<int, N> a;
};

Моя первая попытка double выглядит следующим образом:

template <class N>
Vector<N>&& double1(Vector<N>&& x) 
{ 
  for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
  return static_cast<Vector<N>&&>(x);
}

Сначала все выглядит нормально, но если яdo:

auto x&& = double1(makeVector(1,2,3))

У меня будут ссылки на временные проблемы.

Моя вторая попытка следующая:

template <class N>
Vector<N> double2(Vector<N>&& x) 
{ 
  for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
  return x;
}

К которой, похоже, нет вышеуказанной ссылкик временной проблеме, но делает то, что я считаю ненужным перемещением / копированием по возвращении.

Я мог бы избежать как ссылки на временные проблемы, так и дополнительных перемещений / копий, выполнив следующие действия:

template <class N>
void double3(Vector<N>& x) 
{ 
  for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
}

Но тогда я должен внести изменения в аргумент, который я считаю немного грязным.Мне также придется назвать временные имена.

Моя последняя идея заключалась в следующем:

template <class N>
Vector<N> double4(Vector<N> x) 
{ 
  for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
  return x;
}

Что позволило бы избежать всех копий, если параметр был сохранен в том же месте, что и результат,но я не уверен, как это сделать.

В основном я ищу двойную функцию, которая имеет следующие свойства:

(1) Нет ссылок на временные проблемы при назначении с авто.
(2) Нет копий при передаче временного.
(3) Не изменяет аргумент при передаче временного.

У кого-нибудь есть идеи, как соединить эти три вещи вместе?

Редактировать

Возможно, проще говоря, это поведение, которое я хочу.

(1) Если аргумент является временным, изменитеон на месте.
(2) В противном случае сделайте копию.

Ответы [ 2 ]

2 голосов
/ 24 августа 2011

Ваша последняя идея верна и эффективна, продолжайте:

template <class N>
Vector<N> double4(Vector<N> x) 
{ 
  for (int i = 0; i != N, ++i) { x[i] *= 2; }
  return x;
}
1 голос
/ 24 августа 2011

Этот код не имеет смысла.

Во-первых, std :: array принимает два параметра шаблона: тип и размер. Во-вторых, std :: array является агрегатом; это не очень подвижно. Содержимое может быть перемещено, но не сам объект.

В-третьих, вы злоупотребляете ссылками на r-значения без видимой выгоды. Если вы хотите что-то удвоить, просто используйте обычную ссылку, как это было бы до C ++ 0x.

Но тогда я должен внести изменения в аргумент, который я считаю немного беспорядочным. Я также должен назвать временные имена.

Нет ничего плохого в том, что на самом деле нужно хранить объекты. Не все должно быть временным. Вы абсолютно не получаете эффективности, пытаясь выдвинуть временный вызов функции, если только по той причине, что C ++ не позволяет этого.

И нет ничего «грязного» в изменении параметра; C ++ не является функциональным языком.

Да, и ссылки на r-значения не являются "ссылками на временные данные". Они могут ссылаться на временные данные, но это не единственное, что они делают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...