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?

Jake Schmidt
  • 1,558
  • 9
  • 16
  • 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. – 1201ProgramAlarm Jul 04 '21 at 20:23
  • 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 provided – Jake Schmidt Jul 04 '21 at 20:25
  • 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? – Jake Schmidt Jul 04 '21 at 20:26

1 Answers1

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.

erenon
  • 18,838
  • 2
  • 61
  • 93
  • in c++20 clang still rejects (to be clear, I mean clang still rejects my version, not yours) – Jake Schmidt Jul 04 '21 at 19:36
  • 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, maybe – Jake Schmidt Jul 04 '21 at 19:37
  • 2
    @JakeSchmidt https://timsong-cpp.github.io/cppwp/n4861/expr.ref#footnote-59 – Language Lawyer Jul 04 '21 at 20:33
  • @LanguageLawyer Nice find, I think that might be the answer, annoyingly, it seems that clang is right – Jake Schmidt Jul 04 '21 at 20:39
  • 1
    @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. – cigien Jul 05 '21 at 01:23
  • @cigien Which bullet in https://timsong-cpp.github.io/cppwp/n4861/expr.const#5 makes `p` from `p.foobar` not constant expression – Language Lawyer Jul 05 '21 at 10:16
  • 1
    @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? – cigien Jul 05 '21 at 21:20