Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Return temporary values and objects that cannot be copied

I know that references can extend the lifetime of a return value in C++. With this phylosophy, I tried the following: I have three clases, 'tensor', 'view' and 'mutable_view'. Operator () on a tensor returns a "const view" object. This view has a private copy constructor so that the view cannot be copied, as it keeps information about the tensor that might not survive beyond the current statement.

#include <iostream>
#include <algorithm>

struct tensor {

  int data[10];

  class view {
    const int *const data;

    view();
    view(const view &);
  public:
    view(const int *new_data) : data(new_data) {}
    int operator*() const { return *data; }
  };

  class mutable_view {
    int *const data;

    mutable_view();
    mutable_view(const mutable_view &);
  public:
    mutable_view(int *new_data) : data(new_data) {}

    void operator=(const view &v) {
      *data = *v;
    }
  };

  tensor(int n) {
    std::fill(data, data+10, n);
  }

  const view operator()(int ndx) const {
    return view(data + ndx);
  }

  mutable_view at(int ndx) {
    return mutable_view(data + ndx);
  }
};


int main()
{

  tensor a(1);
  tensor b(2);

  b.at(2) = a(2);

  for (int i = 0; i < 10; i++)
    std::cout << "a[i] = " << b.data[i] << std::endl;

  for (int i = 0; i < 10; i++)
    std::cout << "b[i] = " << b.data[i] << std::endl;

  exit(0);
}

The problem is that, while this code works in gcc (depends on the version), icc signals a warning and open64 simply does not build it: it demands that the constructors from 'view' be public. Reading icc's message the idea seems to be that the right hand value could be potentially copied by the compiler and thus constructors are needed.

Is this really true? Is there a workaround that preserves the syntax I want to build? By the way they are built, and in order to avoid inefficient implementations based on shared_ptr or other stuff, I need to keep the 'view' objects un-copiable.

Edit 1:

tensor cannot control the lifetime of the views. The views are created by the accessors and their lifetime is limited to the statement where they are used, for the following reasons:

  • These views are only used for two things: (i) copying data, (ii) extracting portions of the tensor.
  • The tensors are multidimensional arrays that implement copy-on-write semantics, which means that the views cannot be long-lived objects: if the data changes, they expire.

Edit 2:

Changed the pseudocode description (guys, if you see '...' do you expect it to be compilable?) with one that builds on 'icc' and does not on clang/open64

like image 973
Juanjo Avatar asked Nov 02 '22 05:11

Juanjo


1 Answers

Go ahead and let the default copy constructors be public. And document that a view or mutable_view is "invalidated" when its tensor is changed or destroyed.

This parallels how the Standard Library deals with iterators, pointers, and references that have a lifetime which depends on another object.

like image 120
aschepler Avatar answered Nov 04 '22 12:11

aschepler