lmi
[Top][All Lists]
Advanced

[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

Attachment: pgpVl6r9wcvxH.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]