Date: Sun, 15 Sep 2024 21:17:58 +0200
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"?
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]>
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
> >
>
"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"?
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]>
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:18:11