C++ Logo

std-proposals

Advanced search

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

From: Ivan Lazaric <ivan.lazaric1_at_[hidden]>
Date: Sat, 18 May 2024 16:57:11 +0200
Reflection will enable this: https://godbolt.org/z/hxMrnjs9r

On Sat, May 18, 2024 at 4:18 PM 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 -- cannot be used to instantiate a
> template. I can think of two possible remedies to this problem. The
> first one is very simple:
>
> - - - Remedy 1: Inside the body of a consteval function, allow all
> compile-time constants (including function arguments) to be used to
> instantiate templates.
>
> Remedy 1 would probably be the easiest and best solution. An
> alternative would be:
>
> - - - Remedy 2: Allow the use of a deduction guide in order to treat a
> template as though it were a consteval function, and so then the body
> of the consteval function uses the deduction guide rather than using
> the template directly.
>
> So in order to treat the Factorial template struct as though it's a
> consteval function, you would use a deduction guide something like:
>
> consteval unsigned Monkey(unsigned n) = FactorialT<n>::value;
>
> And so then FactorialC would become:
>
> consteval unsigned FactorialC(unsigned const n)
> {
> return Monkey(n);
> }
>
> I can't right now think of any reason why Remedy 2 would be chosen
> over Remedy 1 -- unless Remedy 1 would just be too much hassle for
> compiler vendors to implement, or if Remedy 1 would mean too many
> alterations to other parts of the Standard.
>
> Can anyone think of any other remedies?
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2024-05-18 14:57:25