2

Why are parameters of immediate (consteval) functions are not considered constant expressions?

consteval void func(int x)
{
   int arr[x]; // not valid, x is not a constant expr
   ...
}

What functionality would have been lost if x was considered a constant expression? Of course every calls to func would have to pass a constant expression as an argument, but this is almost certainly the case anyway, since func is immediate.

If there are some useful cases where an argument to an immediate function can be a non-constant expression, could we require constexpr-ness of a parameter explicitly, as a hypothetical language extension? Would such extension break any existing code or introduce other problems? (It doesn't have to be limited to immediate functions).

consteval void func(constexpr int x)
{
   int arr[x]; // valid, x is a constant expression
   ...
}

func(3); // ok
func(time(nullptr)); // not ok, argument is not a constant expression

Are there any committee papers that explore this design?

I know everything can be done with templates:

template <int x>
consteval void func()
{
   int arr[x]; // valid, x is a constant expression
   ...
}

however templates are syntax-heavy and not very friendly. I would prefer to write myTuple[3] rather than std::get<3>(myTuple). It would be possible if arguments to tuple::operator[] were constexpr. Since today they are not, such operator[] cannot be defined.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • 2
    `template consteval void func() { int arr[X]; }` and `func<3>();` is what you would normally do. – Patrick Roberts Dec 31 '20 at 10:32
  • 1
    @PatrickRoberts I know I can use a template instead but templates are syntax-heavy. I would much prefer to be able to write `x[3]` instead of `std::get<3>(x)`; – n. m. could be an AI Dec 31 '20 at 10:48
  • That makes more sense, perhaps you should mention consteval operator overloading as a motivating factor in your question? – Patrick Roberts Dec 31 '20 at 10:59
  • @PatrickRoberts Well, given that *"consteval specifies that a function is an immediate function, that is, **every call to the function must produce a compile-time constant.**"*, the very first question, here, "Why are parameters of immediate (consteval) functions are not considered constant expressions?" sounds motivating enough, to me (how could they not be constant expressions?). – Bob__ Dec 31 '20 at 11:03
  • 1
    https://stackoverflow.com/questions/56130792/will-consteval-functions-allow-template-parameters-dependent-on-function-argumen – StoryTeller - Unslander Monica Dec 31 '20 at 13:40
  • @StoryTeller-UnslanderMonica close as dup? – dyp Dec 31 '20 at 13:42
  • @dyp - Possibly, yes. It's just that with such dark magic question I prefer not to cast a binding vote. – StoryTeller - Unslander Monica Dec 31 '20 at 13:46
  • @n.'pronouns'm.here's a way you could have a user-defined numeric literal infer the index as a compile-time constant in `my_tuple::operator[]`: https://godbolt.org/z/jhnfdK – Patrick Roberts Dec 31 '20 at 14:46
  • 1
    @PatrickRoberts this is interesting and fun but why reimplement the compiler in user code? :) – n. m. could be an AI Dec 31 '20 at 15:10
  • @n.'pronouns'm. I agree user-defined literals could have some nicer language support. Maybe a standard library numeric literal suffix which creates a `std::integral_constant` of appropriate width, and then a standard template `operator[]` syntactic sugar accepting an instance of `std::integral_constant` as a function parameter might be a straightforward proposal to implement everywhere that `std::get` is currently used. – Patrick Roberts Dec 31 '20 at 15:36
  • @PatrickRoberts That would be useful, but I'd still find the `constexpr` parameter qualification, as proposed by the OP, or even `constinit` far more practical. – Bob__ Dec 31 '20 at 15:58
  • @Bob_ the duplicate seems to have a sufficient explanation as to why that might probably never be syntactically possible. tl;dr, non-template parameter values should not be able to influence the type of a function. As I've shown though, a literal suffix can be used to capture compile-time constants in trivially inferable type information of the function. – Patrick Roberts Dec 31 '20 at 16:07
  • @n.'pronouns'm. as it turns out, `boost::hana::tuple` already does exactly what I described above: [`operator[]`](https://www.boost.org/doc/libs/1_67_0/libs/hana/doc/html/structboost_1_1hana_1_1tuple.html#acef38216a6c6da0296a5f7b5241e951b) and [`operator""_c`](https://www.boost.org/doc/libs/1_67_0/libs/hana/doc/html/structboost_1_1hana_1_1integral__constant.html#a1c078fd00db48686ca9e0aa17f47344e) – Patrick Roberts Dec 31 '20 at 17:03
  • @PatrickRoberts yes, the duplicate does this in the C++17 context, C++20 brings in abbreviated templates. So a function parameter designated with `constexpr` could trigger an abbreviated template, just like `auto` parameters do. – n. m. could be an AI Dec 31 '20 at 19:17
  • 3
    I guess you should track the evolution of [P1045R1](http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p1045r1.html), mentioned in Barry's answer. – Bob__ Dec 31 '20 at 20:06

0 Answers0