Date: Sun, 15 Sep 2024 17:22:03 +0100
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
>
> 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 16:22:07