C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Marrying consteval with template metaprogramming

From: Jason McKesson <jmckesson_at_[hidden]>
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.

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