C++ Logo

std-proposals

Advanced search

Re: [std-proposals] constraint that function can/shall be evaluated at compile time

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sun, 15 Sep 2024 20:50:45 +0100
On 15/09/2024 20:17, Robin Savonen Söderholm wrote:
> Ok, thank you both for your answers. Do I understand you correctly with
> the "core constant expression" vs. "constant expression" that the former
> means "unconditionally constexpr (given that arguments are available in
> compile-time)" while the latter means "constexpr for some branch-path
> depending on input parameter"?

No, these are terms defined in the standard:

https://eel.is/c++draft/expr.const#5 and
https://eel.is/c++draft/expr.const#14

The gist is that "core constant expressions" are the expressions that
are allowed somewhere within constant evaluation, while "constant
expressions" are the end result of such constant evaluations with
additional constraints.

For example:

constexpr int* foo(int&& x) { return &x; }

// foo(42) is allowed within constant evaluation,
// that is foo(42) is a core constant expression
constexpr auto x = *foo(42); // x is int with value 42

// ERROR: pointer to temporary is not a constant expression,
// therefore foo(42) is not a constant expression
constexpr auto y = foo(42);

The difference is subtle.

This has nothing to do with unconditional behaviour, you can only
reasonably reflect on either with fixed argument values.

>
> In that case I personally see 2 cases that are interesting (and perhaps
> viable): the "unconditionally constexpr" and "constexpr given a specific
> input". Having a concept say that "it may be constexpr for some input
> but we don't know which" is probably not that useful, but I may be wrong...
>
> // Robin
>
> On Sun, Sep 15, 2024 at 6:22 PM Lénárd Szolnoki <cpp_at_[hidden]
> <mailto:cpp_at_[hidden]>> wrote:
>
>
>
> On 15/09/2024 09:36, Robin Savonen Söderholm via Std-Proposals wrote:
> > Hi!
> >
> > Another thing I found that I'd like in concepts is the notion
> that e.g.
> > a function related to a type can or shall be evaluated at compile
> time.
> > For example, this:
> > ```c++
> > template <typename T>
> > concept has_foo = requires() {
> > { T::foo() /*consteval*/ } -> is_foo_like;
> > };
>
> Some of this is possible, although rather ugly.
>
> template <typename T>
> concept has_foo = requires {
> // T::foo() is a core constant expression
> ( int(*)[((void)T::foo(), 1)] )nullptr;
>
> { T::foo() /*consteval*/ } -> is_foo_like;
> };
>
> There are variations on this that are more or less ugly with different
> trade-offs.
>
> It's worth noting that you can potentially reflect on two distinct
> properties: whether an expression is a "core constant expression" or
> whether it is a "constant expression", the latter being stricter. The
> trick above reflects on the expression being a core constant expression.
>
> With a similar trick you can reflect on the expression being a constant
> expression and structural. This is something you usually want if you
> want to check if an expression is usable as a condition in `if
> constexpr` for example.
>
> I'm not aware of a trick that allows you to reflect on an expression
> with non-structural type being a "constant expression".
>
> I wouldn't be against a convenience syntax that allows reflecting on
> these properties of expressions. But it is two distinct properties,
> "core constant expression" and "constant expression".
>
> The limitations that Arthur outlined in his email apply too, you can't
> really reflect on constexpr-ness and have unspecified arguments.
>
> > ```
> > This is because I may want to use the result of `foo` to distinguish
> > what kind of reflections I should be allowed to use on `T`, and what
> > should be considered a compile error. I.e. I want to use it as:
> > ```c++
> > void bar(has_foo auto const& my_t) {
> > if constexpr(T::foo(/*possible use of consteval arguments as
> well*/) ==
> > something_else) {
> > do_foo_only_stuff(my_t);
> > }
> > }
> > ```
> >
> > // Robin
> >
>

Received on 2024-09-15 19:50:48