Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 829
skypjack Avatar asked Jul 23 '19 13:07

skypjack


People also ask

What is the use of reference_wrapper?

A reference_wrapper can be used to store references in standard containers, and to pass objects by reference to std::bind . The type Ty must be an object type or a function type, or a static assert fails at compile time. The helper functions std::ref and std::cref can be used to create reference_wrapper objects.

What is reference_wrapper C++?

(since C++11) std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.


2 Answers

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

like image 124
NathanOliver Avatar answered Oct 21 '22 10:10

NathanOliver


There is no guarantee in the standard.

No sensible implementation is going to use more than a pointer.

static_assert it fits and you have enough alignment so your code is correct (and people can see it is correct). That static assert won't ever be hit.

like image 26
Yakk - Adam Nevraumont Avatar answered Oct 21 '22 11:10

Yakk - Adam Nevraumont