Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RVO with a standard layout struct without any constructors

Tags:

c++

c++11

rvo

I have a struct representing a binary message. I want to write a function to get the next such record from a buffer (whether a file or a socket, doesn't matter):

template <typename Record>
Record getNext();

Now, I could write this like:

template <typename Record>
Record getNext() {
    Record r;
    populateNext(reinterpret_cast<char*>(&r),  // maybe ::read()
                 sizeof(r));                   // or equivalent
    return r;
}

which is nice and gives me the benefits of RVO. However, it will invoke the default constructor of Record, which may be composed of types with non-trival default constructors which do work that I would like to avoid - these are not necessarily POD types, but they are standard layout.

Is there a way to write getNext() such that we avoid any constructors (default or copy/move) on Record? Ideally, when the user calls:

auto record = getNext<Record>();

The buffer is read directly into the memory of record. Is this possible?

like image 805
Barry Avatar asked Jun 09 '15 15:06

Barry


People also ask

Do I need a constructor for a struct?

Technically, a struct is like a class , so technically a struct would naturally benefit from having constructors and methods, like a class does.

Can struct have empty constructor?

C# does not allow a struct to declare a default, no-parameters, constructor. The reason for this constraint is to do with the fact that, unlike in C++, a C# struct is associated with value-type semantic and a value-type is not required to have a constructor.

Does a struct have a constructor?

struct can include constructors, constants, fields, methods, properties, indexers, operators, events & nested types. struct cannot include a parameterless constructor or a destructor. struct can implement interfaces, same as class. struct cannot inherit another structure or class, and it cannot be the base of a class.

How do you initialize a class structure in C++?

// In C++ We can Initialize the Variables with Declaration in Structure. Structure members can be initialized using curly braces '{}'.


1 Answers

no_init is a constant of type no_init_t.

If you construct a pod from a no_init_t, you get an uninitialized pod, and (assuming elision) there is nothing to be done.

If you construct a non-pod from a no_init_t, you have to override a constructor, and make it not initialize the data. Usually class_name(no_init_t):field1(no_init), field2(no_init){} will do it, and sometimes class_name(no_init_t){} will do it (assuming all contents are pod).

Constructing from no_init on each member can act as a sanity check that the members are indeed pod, however. A non-pod class constructed from no_init will fail to compile until you write the no_init_t constructor.

This (having to no_init each member constructor) does generate some annoying DRY failure, but we don't got reflection, so you are gonna repeat yourself and like it.

namespace {
  struct no_init_t {
    template<class T, class=std::enable_if_t<std::is_pod<T>{}>>
    operator T()const{
      T tmp;
      return tmp;
    }
    static no_init_t instance() { return {}; }
    no_init_t(no_init_t const&) = default;
  private:
    no_init_t() = default;
  };
  static const no_init = no_init_t::instance();
}


struct Foo {
  char buff[1000];
  size_t hash;
  Foo():Foo(""){}
  template<size_t N, class=std::enable_if_t< (N<=sizeof(buff)) >>
  Foo( char const(&in)[N] ) {
    // some "expensive" copy and hash
  }
  Foo(no_init_t) {} // no initialization!
};
struct Record {
  int x;
  Foo foo;
  Record()=default;
  Record(no_init_t):
    x(no_init), foo(no_init)
  {}
};

Now we can construct Record with no_init and it won't be initialized.

Every POD class is not initialized. Every non-POD class must provide a no_init_t constructor (and presumably implement non-initialization, as best it can).

You then memcpy right over it.

This requires modifying your type, and the types it contains, to support non-initialization.

like image 167
Yakk - Adam Nevraumont Avatar answered Oct 06 '22 13:10

Yakk - Adam Nevraumont