2

My api would require calling runtime(constFoo(str)) to get the final result, I wanted to shorten this because the real function names are kind of verbose. To do this I need to somehow wrap the consteval function, but I can't do that since the argument cannot be constexpr, it's also a string literal which requires the its size to be known at compile time.

I'm aware of Pass const expression to consteval function through non-consteval functions but it doesn't really solve my issue because I need the size to be known at compile time.

int runtime(int val) {
  std::string foo = "foo"; // some run time operation
  return val + 2;
}

template <std::size_t N> consteval int constFoo(const char (&data)[N]) {
  // ...
  const auto d = data[0];
  return N;
}

template <std::size_t N> int outer(const char (&data)[N]) {
  int val = constFoo(data); // Call to consteval function 'constFoo<2ULL>' is not a constant expression
  return runtime(val);
}

int main() {
  auto d = outer("d");
}

Also if this would be somehow possible I'd rather avoid a solution where the literal is passed as a template argument, but as far as I'm aware this is impossible.

3
  • Seems kind of like an XY problem to me. An API should not even expose that much detail, what is the simplest function you can provide on your API is that outer("d") or can your api even be more simple like outer_d()? If so it doesn't matter you have to type a little more or less in your (internal) implementation of said API. Commented Jul 24 at 11:04
  • So what do you try to solve with this? Instead of focusing on this how. Commented Jul 24 at 11:05
  • @PepijnKramer The constFoo and runtime functions are also a part of the api, it's just that there is a usecase where they don't need to be called at the same time, so I cannot just provide outer. Commented Jul 24 at 11:23

2 Answers 2

8

Since C++20, non-type template parameter allows some literal class types, so turn your string literal into one of those classes:

template <std::size_t N>
struct LiteralString
{
    consteval LiteralString(const char (&s)[N]) { std::copy(s, s + N, &data[0]); }

    static constexpr std::size_t size = N;
    char data[N]{};
};

// [..]

template <LiteralString data>
int outer()
{
  int val = constFoo(data.data);
  return runtime(val);
}

int main()
{
  auto d = outer<LiteralString("d")>();
  // [..]
}

Demo

Sign up to request clarification or add additional context in comments.

1 Comment

slight improvement Can call outer<"d"> directly.
2

Make the parameter of the outer (non-consteval) function a class with a consteval constructor taking a string.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.