[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Should lmi use 'consteval' yet?
From: |
Vadim Zeitlin |
Subject: |
Re: [lmi] Should lmi use 'consteval' yet? |
Date: |
Sun, 9 May 2021 18:49:52 +0200 |
On Sun, 9 May 2021 14:14:13 +0000 Greg Chicares <gchicares@sbcglobal.net> wrote:
GC> Using latest lmi HEAD, I was surprised that I can do this (using std::array
GC> to test for compile-time-constant-ness--instead of C arrays, in case the
GC> compiler offers variable-length arrays):
GC>
GC> std::array<int, static_cast<int>( C0.cents())> arr0; // no
surprise
GC> std::array<int, static_cast<int>(10_cents .cents())> arr1; // I'm
surprised
GC>
GC> even though operator""_cents() can throw (here's the implementation
GC> for reference):
I can't give you the chapter and verse of the Standard, but I'm pretty
sure that the idea here is that when constexpr function is evaluated at
compile-time, it is really fully evaluated and its value is also entirely
computed at compile-time and so it doesn't matter if the constexpr function
_can_ throw, if it does _not_ throw for the actual value of the parameter.
I.e. in this case you'd only get a (compile-time) error if you tried to
make an array of a size greater than limit.
A simple example showing this:
---------------------------------- >8 --------------------------------------
% cat constexpr.cpp
#include <array>
constexpr int sq(int n) {
if (n < 0)
throw "invalid input";
return n*n;
}
std::array<int, sq(17)> arr;
% g++-11 -std=c++20 -fsyntax-only -Wall constexpr.cpp && echo ok
ok
% clang++-12 -std=c++20 -stdlib=libc++ -fsyntax-only -Wall constexpr.cpp &&
echo ok
ok
% sed -i'' 's/17/-1/' constexpr.cpp
% g++-11 -std=c++20 -fsyntax-only -Wall constexpr.cpp && echo ok
constexpr.cpp:10:19: in ‘constexpr’ expansion of ‘sq(-1)’
constexpr.cpp:5:9: error: expression ‘<throw-expression>’ is not a constant
expression
5 | throw "invalid input";
| ^~~~~~~~~~~~~~~~~~~~~
constexpr.cpp:10:19: note: in template argument for type ‘long unsigned int’
10 | std::array<int, sq(-1)> arr;
| ~~^~~~
% clang++-12 -std=c++20 -stdlib=libc++ -fsyntax-only -Wall constexpr.cpp &&
echo ok
constexpr.cpp:10:17: error: non-type template argument is not a constant
expression
std::array<int, sq(-1)> arr;
^~~~~~
constexpr.cpp:5:9: note: subexpression not valid in a constant expression
throw "invalid input";
^
constexpr.cpp:10:17: note: in call to 'sq(-1)'
std::array<int, sq(-1)> arr;
^
1 error generated.
---------------------------------- >8 --------------------------------------
GC> I would have reasoned that "10_cents" isn't required to be evaluated
GC> at compile time
This is true, generally speaking. But you force its evaluation at
compile-time by using it in compile-time context.
GC> Even though the compiler is allowed to accept that, is it required to?
Yes, I'm pretty sure it is.
GC> But that academic question leads to a better, pragmatic one: shouldn't I
GC> just tell the compiler what I really, really want, as follows?
GC>
GC> - inline constexpr currency operator""_cents(unsigned long long int cents)
GC> - inline consteval currency operator""_cents(unsigned long long int cents)
GC> ^^^ eval instead of expr
I think this function could indeed be consteval because it is only applied
to literal, i.e. compile-time, values, and so the only (AFAIK) advantage of
"constexpr", i.e. that it can be used both during compile- and run-time,
doesn't apply here. Please take my opinion with a grain of salt, however,
as I haven't actually used consteval in any real code yet and so I could
well be missing something and using it might have some other drawbacks that
I'm unaware of. But right now I would say that all functions that can be
made "consteval" should be made "consteval", and that this one does fall in
this category.
Also, one thing that I am sure about, is that you don't need "inline" any
longer as "consteval" always implies "inline", so it should be removed.
GC> Or should I wait until we're sure all compilers have implemented
'consteval'?
If we require gcc >= 10, as per [*], we can require consteval too, I
think. But, again, I have no practical experience with it yet and little
knowledge about it even theoretically, so I could be missing something
here.
[*] https://lists.nongnu.org/archive/html/lmi/2021-05/msg00004.html
VZ
pgpVl6r9wcvxH.pgp
Description: PGP signature