Is accessing a static constexpr member from a placement new a constant expression?
Asked Answered
A

1

6

To clarify, is the following program well-formed?

#include <new>
char foo[32];
struct bar {
        static constexpr int foobar = 42;
};

int main() 
{
        auto p = new (foo) bar();
        static_assert(p->foobar == 42);
}

gcc and msvc accept, but clang rejects with the error read of non-constexpr variable 'p' is not allowed in a constant expression, who is right?

Asdic answered 4/7, 2021 at 19:24 Comment(3)
This comes down to whether dereferencing a non-constexpr pointer to access a name that resolves to a compile time constant is considered a compile time constant. You get similar sorts of errors with a case p->foobar: statement.Coastward
I think rather it comes down to if it is necessary to dereference a non-constexpr pointer to access a static constexpr member variable with the syntax providedAsdic
A similar thing is done by libraries such as boost/hana for constexpr accessing operators on map, where the "this" pointer is never touched. Does using the syntax provided necessitate touching the "this" pointer?Asdic
G
0

If you change it to:

auto constexpr p = new (foo) bar();

Then the clang error message becomes clearer:

<source>:12:24: error: constexpr variable 'p' must be initialized by a constant expression
        auto constexpr p = new (foo) bar();
                       ^   ~~~~~~~~~~~~~~~
<source>:12:28: note: dynamic memory allocation is not permitted in constant expressions until C++20
        auto constexpr p = new (foo) bar();
                           ^

So the answer depends on the C++ language version.

Gadid answered 4/7, 2021 at 19:35 Comment(7)
in c++20 clang still rejects (to be clear, I mean clang still rejects my version, not yours)Asdic
also, we don't need to read the value of p to get access to the static constexpr member, so p need not be a constant expression, maybeAsdic
@JakeSchmidt timsong-cpp.github.io/cppwp/n4861/expr.ref#footnote-59Coequal
@LanguageLawyer Nice find, I think that might be the answer, annoyingly, it seems that clang is rightAsdic
@LanguageLawyer If that footnote means p needs to be a constant expression, wouldn't auto p = bar(); static_assert(p.foobar == 42); also be an error? But it's not, and Clang accepts it.Pentup
@Pentup Which bullet in timsong-cpp.github.io/cppwp/n4861/expr.const#5 makes p from p.foobar not constant expressionCoequal
@LanguageLawyer None. IIUC, the bullet that allows new expressions doesn't count, presumably because the lifetime of the expression that allocates memory for p doesn't extend to the static_assert? Also, you seem to know the answer to the OP's question; why not write an answer?Pentup

© 2022 - 2025 — McMap. All rights reserved.