Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

aligned_storage, aligned_union, and how max isn't a constexpr

17 views
Skip to first unread message

Frederick Gotham

unread,
Oct 23, 2019, 2:59:14 AM10/23/19
to

So I was playing around with aligned_storage, and I had something like:

aligned_storage< max(sizeof(A), sizeof(B)),
max(alignof(A), alignof(B)) >::type buf;


But then this wouldn't compile because "max" isn't a constexpr. So next I decided I'd just use a MAX macro instead.

So then I was perusing a reference of the C++11 standard library and I came across aligned_union, which seemed to be exactly what I needed, as the previous code would become:

aligned_union<1, A, B>::type buf;

I'm curious though. . .

How does aligned_union work fine in C++11 if max didn't become a constexpr until C++14 ?

Is this simply a case of "The Standard says it has to work"?

Öö Tiib

unread,
Oct 23, 2019, 4:12:37 AM10/23/19
to
I am not 100% sure but I trust that max can't work because max is required to
return reference to one of its arguments. C++11 allowed reference
constant expressions only to designate objects of static storage duration
or functions. The sizeof invocations are not producing objects of static
storage duration. The later standards relaxed those requirements in
major ways.

>
> Is this simply a case of "The Standard says it has to work"?

That aligned_union was likely implementable already in C++98.

David Brown

unread,
Oct 23, 2019, 5:14:56 AM10/23/19
to
On 23/10/2019 10:12, Öö Tiib wrote:
> On Wednesday, 23 October 2019 09:59:14 UTC+3, Frederick Gotham wrote:
>> So I was playing around with aligned_storage, and I had something like:
>>
>> aligned_storage< max(sizeof(A), sizeof(B)),
>> max(alignof(A), alignof(B)) >::type buf;
>>
>>
>> But then this wouldn't compile because "max" isn't a constexpr. So next I decided I'd just use a MAX macro instead.
>>
>> So then I was perusing a reference of the C++11 standard library and I came across aligned_union, which seemed to be exactly what I needed, as the previous code would become:
>>
>> aligned_union<1, A, B>::type buf;
>>
>> I'm curious though. . .
>>
>> How does aligned_union work fine in C++11 if max didn't become a constexpr until C++14 ?
>
> I am not 100% sure but I trust that max can't work because max is required to
> return reference to one of its arguments. C++11 allowed reference
> constant expressions only to designate objects of static storage duration
> or functions. The sizeof invocations are not producing objects of static
> storage duration. The later standards relaxed those requirements in
> major ways.

A simple "(a > b) ? a : b" will be a constant expression in C++, as long
as "a" and "b" are constant expressions, so I guess aligned_union uses
something like that directly rather than std::max.

Frederick Gotham

unread,
Oct 23, 2019, 5:26:50 AM10/23/19
to
On Wednesday, October 23, 2019 at 10:14:56 AM UTC+1, David Brown wrote:

> A simple "(a > b) ? a : b" will be a constant expression in C++, as long
> as "a" and "b" are constant expressions, so I guess aligned_union uses
> something like that directly rather than std::max.

It's a variadic template, so you can do this:

aligned_union<1,HWND,char*,double,ifreq,std::string>::value buf;

I dunno how they'd pull that off without a 'max' that takes multiple arguments.

Öö Tiib

unread,
Oct 23, 2019, 6:18:48 AM10/23/19
to
By using (a > b) ? a : b recursively like lot of variadic templates do.

Bo Persson

unread,
Oct 23, 2019, 6:47:07 AM10/23/19
to
The implementors can of course write their own constexpr _Max that only
works for std::size_t and returns by value. No reference support needed.


Bo Persson

0 new messages