Date: Sat, 18 May 2024 13:42:57 -0400

On Sat, May 18, 2024 at 10:18 AM Frederick Virchanza Gotham via

Std-Proposals <std-proposals_at_[hidden]> wrote:

>

> At some point we're going to have to make consteval functions

> compatible with template metaprogramming, so let's talk about the

> possible ways of doing that.

>

> First of all, let me start with an example of compile-time Factorial

> as a template struct:

>

> template<unsigned n>

> struct Factorial {

> inline static constexpr unsigned value = n * Factorial<n-1u>::value;

> };

>

> template<>

> struct Factorial<0u> {

> inline static constexpr unsigned value = 1u;

> };

>

> It's possible to rewrite this template struct as a consteval function

> as follows:

>

> consteval unsigned Factorial(unsigned const n)

> {

> if ( 0u == n ) return 1u;

> return n * Factorial(n-1u);

> }

>

> Now let's try get the template to use the consteval function. The

> following works fine:

>

> consteval unsigned FactorialC(unsigned const n)

> {

> if ( 0u == n ) return 1u;

> return n * FactorialC(n-1u);

> }

>

> template<unsigned n>

> struct FactorialT {

> inline static constexpr unsigned value = FactorialC(n);

> };

>

> Now let's try to do it the other way around. Let's try get the

> consteval function to make use of the template:

>

> template<unsigned n>

> struct FactorialT {

> inline static constexpr unsigned value = n * FactorialT(n-1u);

> };

>

> template<>

> struct FactorialT<0u> {

> inline static constexpr unsigned value = 1u;

> };

>

> consteval unsigned FactorialC(unsigned const n)

> {

> return FactorialT<n>(); // compiler error

> }

>

> This fails to compile because the function argument 'n' -- even though

> it's a compile-time constant --

No it isn't. That is in fact the whole problem: function parameters

are never, under *any* circumstances, constant expressions.

When you're dealing with technical issues in the standard, you have to

use standard terminology. There is no such thing as a "compile-time

constant" or "known at compile-time" or even "the compiler". There are

a subset of expressions which are "constant expressions". And certain

functionality (like the arguments given to a template parameter) must

take constant expressions.

Neither of your two remedies would work because neither of them

addresses the actual problem: function parameters are not constant

expressions.

A lot of people have spent a lot of time thinking about how to make

function parameters into constant expressions in a useful way. And

thus far, they haven't really succeeded. You should probably read up

on those before continuing farther. Not that you will, but one would

hope.

Std-Proposals <std-proposals_at_[hidden]> wrote:

>

> At some point we're going to have to make consteval functions

> compatible with template metaprogramming, so let's talk about the

> possible ways of doing that.

>

> First of all, let me start with an example of compile-time Factorial

> as a template struct:

>

> template<unsigned n>

> struct Factorial {

> inline static constexpr unsigned value = n * Factorial<n-1u>::value;

> };

>

> template<>

> struct Factorial<0u> {

> inline static constexpr unsigned value = 1u;

> };

>

> It's possible to rewrite this template struct as a consteval function

> as follows:

>

> consteval unsigned Factorial(unsigned const n)

> {

> if ( 0u == n ) return 1u;

> return n * Factorial(n-1u);

> }

>

> Now let's try get the template to use the consteval function. The

> following works fine:

>

> consteval unsigned FactorialC(unsigned const n)

> {

> if ( 0u == n ) return 1u;

> return n * FactorialC(n-1u);

> }

>

> template<unsigned n>

> struct FactorialT {

> inline static constexpr unsigned value = FactorialC(n);

> };

>

> Now let's try to do it the other way around. Let's try get the

> consteval function to make use of the template:

>

> template<unsigned n>

> struct FactorialT {

> inline static constexpr unsigned value = n * FactorialT(n-1u);

> };

>

> template<>

> struct FactorialT<0u> {

> inline static constexpr unsigned value = 1u;

> };

>

> consteval unsigned FactorialC(unsigned const n)

> {

> return FactorialT<n>(); // compiler error

> }

>

> This fails to compile because the function argument 'n' -- even though

> it's a compile-time constant --

No it isn't. That is in fact the whole problem: function parameters

are never, under *any* circumstances, constant expressions.

When you're dealing with technical issues in the standard, you have to

use standard terminology. There is no such thing as a "compile-time

constant" or "known at compile-time" or even "the compiler". There are

a subset of expressions which are "constant expressions". And certain

functionality (like the arguments given to a template parameter) must

take constant expressions.

Neither of your two remedies would work because neither of them

addresses the actual problem: function parameters are not constant

expressions.

A lot of people have spent a lot of time thinking about how to make

function parameters into constant expressions in a useful way. And

thus far, they haven't really succeeded. You should probably read up

on those before continuing farther. Not that you will, but one would

hope.

Received on 2024-05-18 17:43:09