C++ Logo

std-proposals

Advanced search

[std-proposals] Specify Constant Expression

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sun, 5 Jan 2025 12:32:51 +0000
Consider the following class used to calculate at compile time the
factorial of a number:

    template<unsigned n>
    struct Factorial {
        static constexpr unsigned value = n * Factorial<n-1u>::value;
    };

    template<>
    struct Factorial<0> {
        static constexpr unsigned value = 1u;
    };

Now let's try to double it:

    consteval unsigned DoubleFactorial(unsigned const arg)
    {
        return 2u * Factorial<arg>::value;
    }

This won't compile because 'arg' isn't a constant expression . . .even
though it's inside a consteval function and its value is known at compile
time.

It might be a lot of work to rewrite the standard to specify that the
arguments to a function are constant expressions if the function is
consteval, but maybe it would be a lot less work to add a new feature that
allows us to explicitly specify that a value is a constant expression,
perhaps something like:

    consteval unsigned DoubleFactorial(unsigned const arg)
    {
        [constexpr arg : carg];
        return 2u * Factorial<carg>::value;
    }

The line:

    [constexpr arg : carg];

takes the value of 'arg' which is known at compile time, and turns it into
a constant expression called 'carg' which can be used as a template
parameter.

A more complex use would be something like:

    constexpr unsigned DoubleFactorial(unsigned arg)
    {
        if consteval
        {
            [constexpr arg : carg];
            return 2u * Factorial<carg>::value;
        }
        else
        {
            unsigned retval = 2u;
            while ( arg ) retval *= arg--;
            return arg;
        }
    }

I realise that this feature isn't very pretty and is more of an
improvisation to get around pre-existing language limitations, but it's
nowhere near as bad as forwarding references.

Received on 2025-01-05 12:32:53