This is an archive of the discontinued LLVM Phabricator instance.

Fix some constexpr members in array<T, 0>
AbandonedPublic

Authored by zoecarver on Apr 14 2019, 6:23 AM.

Details

Summary

This fixes bug 40124 based on Richard Smith's suggestion. As he pointed out in the bug comments, this implementation does not take up any more space.

Currently, __wrapper is trivially destructible (I think there is an issue about this for C++20, but I cannot find any specifications about it in the standard. Feel free to post a link, and I can update the patch).

This patch relies on issue 2157 which ensures that _Tp is DefaultConstructible (maybe I should add a check for this?).

Diff Detail

Event Timeline

zoecarver created this revision.Apr 14 2019, 6:23 AM
EricWF requested changes to this revision.Apr 14 2019, 9:47 AM

This doesn't work for a number of reasons. First, the destructor is only trivial when all the union members are. second, you can't put constexpr on functions that never produce a valid constant expression

This revision now requires changes to proceed.Apr 14 2019, 9:47 AM
zoecarver updated this revision to Diff 198154.May 4 2019, 7:23 PM
  • Update tests
  • Union only exist in C++17 and up

Here is an implementation where array<T, 0>{{}} errors (but I don't think it's needed anymore). Additionally, I have tested that all methods which are not intended to error are constant expressions.

Both std::array<T, x> and std::array<T, 0> are not trivially destructible if T is not. Therefore I think it is okay for this patch to be the same (let me know if I am missing something though).

If you give this implementation a thumbsup I will add more tests (and fail tests).

@EricWF do you still have issues with this patch?

ldionne requested changes to this revision.Jun 14 2019, 7:18 AM
ldionne added inline comments.
include/array
307

This can't be marked constexpr because it never produces a constant expression.

319

Ditto, and several times below.

356

You need to do something different based on whether you're in C++17 or not. Make sure you run the tests with multiple standards!

test/std/containers/sequences/array/size_and_alignment.pass.cpp
24

This test is always enabled (even in C++03 mode), so I don't think you can use constexpr here. Also, inline isn't useful here.

Finally, you only need this test in C++17, so you can use generalized constexpr and not do only one awkwardly long expression.

This revision now requires changes to proceed.Jun 14 2019, 7:18 AM
zoecarver marked an inline comment as done.Jun 15 2019, 11:56 AM
zoecarver added inline comments.
include/array
307

You're right. I did not implement/test this properly. There are two things I could do. A) I could remove the constexpr from these methods which would make them error at runtime or B) I could add a non-constexpr static_assert that would fail when one of these methods was used in a program at compile time. I think the later might be UB. Thoughts?

ldionne added inline comments.Jun 17 2019, 8:41 AM
include/array
307

Honestly, I think the only thing we can do here is to not mark it as constexpr. Because there's no way to implement it in a way that it's SOMETIMES a valid constant expression, and the Standard says that it's ill-formed NDR to have a function marked as constexpr that can never produce a constant expression.

@EricWF It seems like maybe I should file a LWG issue because the current spec is not implementable, any opinion?

I think it would be good to have an LWG issue that says something along the lines of, 22.3.7.5 is updated to say:

array shall provide support for the special case N == 0.
In the case that N == 0, begin() == end() == unique value. All member functions remain constexpr.
No element access members shall participate in overload resolution.
Member function swap() shall have a non-throwing exception specification.

Thoughts?

zoecarver abandoned this revision.May 22 2020, 1:25 PM