TL;DR:
- What is the size of a pointer to an empty class
empty_t
? - Does the C++20 attribute
[[no_unique_address]]
have any impact on that pointer size?
Particularly, the first seems to be quite an old question, but it's hard to find information on the Internet (because the search is spoiled by more trivial information on pointers and empty base-class optimization).
Longer story:
I have written a custom container that conditionally contains some parameters some_parameters_t
. In case those are absent, I use [[no_unique_address]]
in order to not increase the size of the object.
This works fine for the plain parameter type. Now, I set up an iterator containing a pointer to this parameters. Is this pointer guaranteed to be empty as well, when the pointee is?
Here is a synthetic example code:
struct some_parameters_t
{
int important_parameter = 42;
};
struct empty_t {};
template<bool use_parameters>
struct my_container
{
using param_t = std::conditional_t<use_parameters, some_parameters_t, empty_t>;
[[no_unique_address]] param_t param_;
vector<double> vec_;
struct iterator
{
iterator(vector<double>* vec, param_t* p) : vec_(vec), p_(p) {}
vector<double>* vec_;
[[no_unique_address]] param_t* p_; //is this guaranteed to have zero size when being empty_t* ?
using param_ptr = std::conditional_t<use_parameters, some_parameters_t*, empty_t>;
[[no_unique_address]] param_ptr p_; //or must I use this conditional_t construct once again to get size 0?
};
//...
};
The question is: When [[no_unique_address]] param_t*
conditionally becomes [[no_unique_address]] empty_t*
, is it guaranteed to be of zero size?
Or, do I have to use the std::conditional_t<use_parameters, some_parameters_t*, empty_t>
trick again, together with [[no_unique_address]] param_ptr p_
in order to arrive at size 0?
The size of the pointer. On modern platforms, all pointers have the same size.
That is not specified.
No.
Yes.
It's really easy to check, just
std::cout << sizeof(my_container<0>::iterator);
and add/remove the member and see if it changes. Etc.