https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110348

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #3)
> I wonder if the paper wording isn't incorrect, or at least comparing the
> clang++
> implementation vs. the paper gives some differences.
> 
> One (minor) is that they emit errors when the size () and/or data () members
> aren't constexpr, while the paper as voted in only requires that
> "- the expression M.size() is implicitly convertible to std::size_t, and
> - the expression M.data() is implicitly convertible to ”pointer to const
> char”."
> unless the static assertion fails.  The WIP patch doesn't do that, only
> effectively diagnoses it during constant evaluation of those when the static
> assertion fails.

I agree with your WIP patch. The requirements for data() and size() to be
constant expressions are in p11 (11.2) which only apply if the static
assertions fails.


> More important, they have in the testcase something similar to what I filed
> in PR111122, but let's use what works also in GCC:
> struct T {
>   const char *d = init ();
>   constexpr int size () const { return 2; }
>   constexpr const char *data () const { return d; }
>   constexpr const char *init () const { return new char[2] { 'o', 'k' }; }
>   constexpr ~T () { delete[] d; }
> };
> constexpr int a = T{}.size (); // Ok, a = 2
> constexpr int b = T{}.data ()[0]; // Ok, b = 'o'
> constexpr const char *c = T{}.data (); // Not constant expression, because
> it returns
> // address from new which is later in the dtor deleted.
> static_assert (false, T{}); // Valid?

Interesting one. The call to .data() occurs before the destructor, so I would
naively expect it to be valid. I think it should be equivalent to:

constexpr int i = (T{}.data(), 0);

The data() pointer is valid during the lifetime of the T prvalue. I would
expect that a failed static assertion creates some kind of scope for the
constant expression M, and evaluation of the data() string occurs before the
destruction of any objects created in that scope.

> I don't know how std::format if constexpr (is it?) or string_view etc. work,

std::format isn't a constexpr function. The "with this proposal" example in
P2741R3 doesn't actually work with that proposal, it would require changes to
std::format that haven't been proposed for the standard.

> do they
> need M.data () not be actual constant expression and only M.data ()[0]
> through M.data ()[M.size () - 1] constant expressions?

string_view doesn't require a data() function in any way, constexpr or not. It
just takes a pointer and optional length.

> In the patch I can
> surely try to constant expr evaluate M.data () quietly and if it isn't
> constant expression, just use a slower way which will ask for each character
> individually.  More important question is what is the intention for the
> standard...

I think it has to be a constant expression, the slower fallback shouldn't be
needed IMHO.

Reply via email to