Search code examples
c++language-lawyerc++17reference-wrapper

Is there any guarantee on the size of an std::reference_wrapper?


Consider the case in which I've enough storage to host a void * and therefore to construct in-place a pointer.
Is there any guarantee that the same storage is big enough to always store also an std::reference_wrapper?

Kind of (written out of my mind, just to give a grasp of what I mean):

std::aligned_storage_t<sizeof(void *), alignof(void *)> storage;
// ...
int value = 0;
new (&storage) std::reference_wrapper<int>{value};

From a quick and dirty test, I see that on my machine this is valid, that is the size of an std::reference_wrapper fits with that of a void *. However it could be the case on different platforms. At the same time, I cannot find any clue in the standard about the size of and std::reference_wrapper and I'm wondering if it's implementation defined or there are any guarantees.


To give a context, I'm working on an opaque wrapper around different types (similar to std::any) that performs a small object optimization to avoid allocations when possible.
When I receive an std::reference_wrapper, I want to use a different path than that used to differentiate sizeof(T) > sizeof(void *) from the other case around. However, I don't know if I can just copy construct in-place the wrapper or if I should rely on allocations also in this case instead.


Solution

  • The C++ standard does not pose any size requirements. Per [refwrap]

    1. reference_­wrapper<T> is a Cpp17CopyConstructible and Cpp17CopyAssignable wrapper around a reference to an object or function of type T.
    2. reference_­wrapper<T> is a trivially copyable type.

    All we know is that is copyable, and it is trivial. Other than that it it left up to the implementation. Typically it is just a wrapper for a T*, but the implementation might have some other members in there for some reason