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.