C ++ 11: предотвращение назначения объекта для ссылки - PullRequest
3 голосов
/ 07 октября 2011

Есть ли способ создать тип A такой, что:

Дано:

A f(...);

Тогда:

И auto&& a = f(...);, и const auto& a = f(...); выдают ошибки компиляции?

Причина этого в том, что в данном случае A является шаблоном выражения, который содержит ссылки на временные ссылки (которые предоставляются в качестве аргументов для f), поэтому я не хочу, чтобы время жизни этого объекта было расширено за пределы текущее выражение.

Примечание. Я могу предотвратить возникновение проблемы auto a = f(...);, просто сделав A конструктор копирования закрытым, и сделав f(...) другом A, если потребуется.

Пример кода (ссылка ideone) :

#include <iostream>
#include <array>

template <class T, std::size_t N>
class AddMathVectors;

template <class T, std::size_t N>
class MathVector
{
public:
  MathVector() {}
  MathVector(const MathVector& x) 
  { 
    std::cout << "Copying" << std::endl;
    for (std::size_t i = 0; i != N; ++i)
    {
      data[i] = x.data[i];
    }
  }
  T& operator[](std::size_t i) { return data[i]; }
  const T& operator[](std::size_t i) const { return data[i]; }
private:
  std::array<T, N> data;
};

template <class T, std::size_t N>
class AddMathVectors
{
public:
  AddMathVectors(const MathVector<T,N>& v1, const MathVector<T,N>& v2) : v1(v1), v2(v2) {}
  operator MathVector<T,N>()
  {
    MathVector<T, N> result;
    for (std::size_t i = 0; i != N; ++i)
    {
      result[i] = v1[i];
      result[i] += v2[i];
    }
    return result;
  }
private:
  const MathVector<T,N>& v1;
  const MathVector<T,N>& v2;
};

template <class T, std::size_t N>
AddMathVectors<T,N> operator+(const MathVector<T,N>& v1, const MathVector<T,N>& v2)
{
  return AddMathVectors<T,N>(v1, v2);
}

template <class T, std::size_t N>
MathVector<T, N> ints()
{
  MathVector<T, N> result;
  for (std::size_t i = 0; i != N; ++i)
  {
    result[i] = i;
  }
  return result;
}

template <class T, std::size_t N>
MathVector<T, N> squares()
{
  MathVector<T, N> result;
  for (std::size_t i = 0; i != N; ++i)
  {
    result[i] = i * i;
  }
  return result;
}

int main()
{
  // OK, notice no copies also!
  MathVector<int, 100> x1 = ints<int, 100>() + squares<int, 100>(); 

  // Should be invalid, ref to temp in returned object
  auto&& x2 = ints<int, 100>() + squares<int, 100>(); 
}

1 Ответ

5 голосов
/ 07 октября 2011

Для любого временного объекта в C ++ всегда допустимо продлить время жизни этого временного объекта, привязав его к переменной const& или &&.В конечном счете, если вы имеете дело с отложенной оценкой и т.п., вы должны попросить пользователя не использовать const auto & или auto &&.В C ++ 11 нет ничего, что позволяло бы принудительно запрещать пользователю делать это.

...