0

The boost::aligned_storage data type is useful to me in order to provide aligned storage in a pre-c++11 world. I have a class that contains this storage member:

template <size_t StoreSize>
class RoutineStorage {
   enum { ROUTINE_STORAGE_SIZE = StoreSize};
   enum { BUFFER_ALIGNMENT_VALUE = 8 };

   template <typename TStorageType> TStorageType& getStorageAsType()
   {
       BOOST_STATIC_ASSERT_MSG(boost::has_trivial_assign<TStorageType>::value &&
         boost::has_trivial_copy<TStorageType>::value,
         "The storage type must be trvially copyable and assignable to support this classes "
          "copy|assign semantics.");
        ... // Checking and some other code.
        return new (_store.address()) TStorageType();
   }

private:
    typedef boost::aligned_storage<ROUTINE_STORAGE_SIZE, BUFFER_ALIGNMENT_VALUE> 
        StorageBuffer;

    StorageBuffer _store;
}

I would like to provide a copy constructor for this class, but when i look at the implementation of aligned_storage it has a copy constructor listed as private and a comment // noncopyable. There doesn't seem to be an explanation for this in any of the boost pages about this type, so i concluded that they didn't want to handle copying of different possible templated buffer sizes. I suspect that the following will be fine for copying this buffer:

RoutineStorage(const RoutineStorage<StoreSize>& copy)
{
    std::memcpy(_store.address(), copy._store.address(), _store.size())
}

Will there be a problem with this? As far as i can tell the aligned_buffer address function will give the start of a continues memory address and size will let me always copy the correct size.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175

1 Answers1

1

Just copying the buffer like you do in

RoutineStorage(const RoutineStorage<StoreSize>& copy)
{
    std::memcpy(_store.address(), copy._store.address(), _store.size())
}

is not enough. Yes, you will have an exact copy, but you don't actually have the object you created in that StorageBuffer. [intro.object]\1 states that

The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is created by a definition ([basic.def]), by a new-expression, when implicitly changing the active member of a union ([class.union]), or when a temporary object is created ([conv.rval], [class.temporary]).

so until you copy the object into store with placement new you don't actually have an object, just storage.

Lets say you are storing a Foo. Originally you would create the Foo in the StorageBuffer like

Foo* f = new(_store.address()) Foo();

So, in the copy constructor you just need to call the copy constructor of Foo and placing that into _store like

RoutineStorage(const RoutineStorage<StoreSize>& copy)
{
    f = new(_store.address()) Foo(copy.*f);
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Ok, so the class does not know the object that will be stored in its buffer when it is being copied. The user of the class gets the type they require from the buffer. If i static assert that the object is trivial as in the edit to the question, is this enough? – Fantastic Mr Fox Sep 21 '18 at 13:37
  • @FantasticMrFox It is not. I'm looking up the relevant standard section right now to show you just having a buffer is not the same as having an object. – NathanOliver Sep 21 '18 at 13:38
  • Ok, there is a question on it here: https://stackoverflow.com/questions/30114397/constructing-a-trivially-copyable-object-with-memcpy – Fantastic Mr Fox Sep 21 '18 at 13:42
  • @FantasticMrFox Awesome find. I've also updated the answer with the relevant standardess – NathanOliver Sep 21 '18 at 13:44
  • Hnnnn, this implies the opposite: https://stackoverflow.com/questions/26171827/is-memcpy-of-a-trivially-copyable-type-construction-or-assignment How is this so hard ... – Fantastic Mr Fox Sep 21 '18 at 13:49
  • @FantasticMrFox Not really. What they are missing there is everything they quote says `object`. You don't actually have an object though until you follow what [intro.object]/1 says – NathanOliver Sep 21 '18 at 13:53