Compile-Time Evaluation

constexpr, consteval, and Coroutines

Can I use constexpr or consteval with coroutines?

Illustration representing computer hardware

The interaction between constexpr/consteval and coroutines is an interesting topic in C++20 and beyond. Let's explore this:

Basic Rule

As of C++20, coroutines cannot be constexpr or consteval. The coroutine machinery involves runtime operations that are not compatible with compile-time evaluation.

Coroutine Basics

First, let's recall what a basic coroutine looks like:

#include <coroutine>
#include <iostream>

struct MyCoroutine {
  struct promise_type {
    int value;
    MyCoroutine get_return_object() {
      return MyCoroutine{this};
    }
    std::suspend_always initial_suspend() {
      return {};
    }
    std::suspend_always final_suspend() noexcept {
      return {};
    }
    void unhandled_exception() {}
    std::suspend_always yield_value(int v) {
      value = v;
      return {};
    }
  };

  std::coroutine_handle<promise_type> h;
  MyCoroutine(promise_type* p)
    : h(std::coroutine_handle<
      promise_type>::from_promise(*p)) {}
  ~MyCoroutine() {
    if (h) h.destroy();
  }
};

MyCoroutine simple_coroutine() {
  co_yield 1;
  co_yield 2;
  co_yield 3;
}

int main() {
  auto cor = simple_coroutine();
  for (int i = 0; i < 3; ++i) {
    cor.h.resume();
    std::cout << cor.h.promise().value << ' ';
  }
}
1 2 3

Why Coroutines Can't Be constexpr

Coroutines involve several runtime operations:

  • Memory allocation for the coroutine frame
  • Suspension and resumption of execution
  • Potential dynamic dispatch through virtual function calls

These operations are not compatible with compile-time evaluation, which is why coroutines can't be constexpr or consteval.

Compile-Time Friendly Alternatives

While coroutines themselves can't be constexpr, you can still use constexpr functions to generate or manipulate coroutine-related data:

#include <array>
#include <coroutine>
#include <iostream>

constexpr std::array<int, 3> generate_values() {
  return {1, 2, 3};
}

struct MyCoroutine {/*...*/}; MyCoroutine value_coroutine() { constexpr auto values = generate_values(); for (int v : values) { co_yield v; } } int main() { auto cor = value_coroutine(); for (int i = 0; i < 3; ++i) { cor.h.resume(); std::cout << cor.h.promise().value << ' '; } }
1 2 3

Future Developments

The C++ committee is discussing potential ways to make coroutines more compile-time friendly in future standards. Some proposals include:

However, as of C++20, these are still in the proposal stage and not part of the standard.

  • Compile-time coroutines for metaprogramming
  • Static coroutines that don't require dynamic allocation

Compile-Time Metaprogramming Alternative

For compile-time sequential computation, you might consider using template metaprogramming techniques instead of coroutines:

While this approach is less intuitive than coroutines, it achieves compile-time sequential computation.

#include <iostream>

template <int... Sequence>
struct sequence {};

template <int N, int... Sequence>
struct generate_sequence : generate_sequence<
  N - 1, N - 1, Sequence...> {};

template <int... Sequence>
struct generate_sequence<0, Sequence...> {
  using type = sequence<Sequence...>;
};

template <int... Seq>
constexpr void print_sequence(sequence<Seq...>) {
  ((std::cout << Seq << ' '), ...);
}

int main() {
  print_sequence(
    typename generate_sequence<3>::type{}
  );
}
0 1 2

In conclusion, while coroutines themselves cannot be constexpr or consteval in C++20, you can still use compile-time computation in conjunction with coroutines.

As the language evolves, we may see more integration between compile-time evaluation and coroutines in future C++ standards.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved