1

For example I got this code:

constexpr static std::size_t ConstexprFunction(const int value) {
  return value;
}

static constexpr std::size_t CallConstexptrFunction(const int value) {
  constexpr std::size_t v = ConstexprFunction(value);
  return v;
}

int main() {
  constexpr int test = 42;
  CallConstexptrFunction(test);
}

the compiler will argued that constexpr variable 'v' must be initialized by a constant expression, it looks like the ConstexprFunction is actually run on runtime, not on compile-time. I change the code to this:

static constexpr std::size_t CallConstexptrFunction(const int value) {
  constexpr std::size_t v = value;
  return v;
}

int main() {
  constexpr int test = 42;
  CallConstexptrFunction(test);
}

and the error keeps the same, which may prove that when use the value in the CallConstexptrFunction, it is considered to a runtime variable rather than a contexpr variable.

currently my solution is to change the function parameter to a template parameter to avoid parameter passing:

constexpr static std::size_t ConstexprFunction(const int value) {
  return value;
}

template<int SIZE>
static constexpr std::size_t CallConstexptrFunction() {
  constexpr std::size_t v = ConstexprFunction(SIZE);
  return v;
}

there's a similarly question, but the question:

  1. It is based on C++11.
  2. One of the OP's solution makes the function run on runtime, don't know the OP award that or not (the case he called the returned the function directly, not hold the return value by a constexpr variable).

and after reading the question here's my questions:

  1. Will the template version generate too many instances which will lead the code size to be too large?
  2. Can the function parameter passing be done without using template (any version is welcome, even C++20), I tried constexpr int value as parameter and use Clang and C++20 experimental, it seems this syntax is still not allowed.
  • Even for `consteval` functions, that *must* be constant evaluated, the parameter are not themselves constant expressions. So nothing changed since the question you found. Use a template. – StoryTeller - Unslander Monica Sep 09 '20 at 09:19
  • @StoryTeller-UnslanderMonica then how about the code size? –  Sep 09 '20 at 09:21
  • Can't tell you. I've never noticed a difference, nor have I seen anybody else who measured and reported a difference. But then again I always used it in contexts that require constant evaluation anyway. – StoryTeller - Unslander Monica Sep 09 '20 at 09:35

1 Answers1

1

In context of CallConstexptrFunction, expression ConstexprFunction(value) is not constexpr because of value can possibly have a dynamic lifetime, so initialization of v is illegal.

Proper way would be do something like this

constexpr std::size_t ConstexprFunction(const int value) {
  return value;
}

constexpr std::size_t CallConstexptrFunction(const int value) {
  return  ConstexprFunction(value);
}

int main() {
  constexpr int test = 42;
  constexpr auto res = CallConstexptrFunction(test);
  return res;
}

CallConstexptrFunction(test) in main() is a constexpr expression. So compiler would happily evaluate it, generating something like following code.

    mov     eax, 42
    ret
Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • Hi, thanks for pointing out the compiler optimization, I think you answer is convincing, but I still got some worries, do you have any evidence that compiler will always do the evaluate, no matter how complicated the constexpr function is? Language level solutions always make me more relaxed :) –  Sep 09 '20 at 09:37
  • 1
    @ravenisadesk that's promised by the c++ standart. Unfortunately, there is a limited number of what can be used within a constexpr function as many operations aren't constexpr. The list of allowed operations is expanded with each iteration of C++ standart. If function takes too much time then the compilation time will also rise which might eventually lead to builds too long. So be mindful. – ALX23z Sep 09 '20 at 09:46
  • `constexpr auto res` being a `constexpr` ensures that `res` is compile-time. It IS language solution. Forbidding user to call `CallConstexptrFunction` with non-constexpr argument in non-explicit cases makes little sense. why? if they are inline, they will be "unraveled" in resulting code. If it really necessary they should be template arguments, which equals to explicit compile-time as well. – Swift - Friday Pie Sep 09 '20 at 09:48
  • @Swift-FridayPie because in my case I have cpu instructions to do the same job, the function get run on runtime is not acceptable, since only few operations can be used in constexpr functions, what I want is not in that list, which lead to a efficiency problem. I think forbid user to use constexpr functions on runtime sometimes makes sense. –  Sep 09 '20 at 09:52
  • and as my experiences, due to the limitation of operations used in a constexpr function, the constexpr function usually has a better runtime solution, that's why I don't like constexpr functions get called on runtime. –  Sep 09 '20 at 09:57
  • @ravenisadesk for purpose like that I used `integral_constant`s and similar templates , doable even in C++98, because you can implement those even before C++11. Modern C++ gives that template a functional format, but templates are limited to integer values. Wasn't a problem because *real* real-time code is likely not using IEEE754 at all. – Swift - Friday Pie Sep 09 '20 at 10:00