Skip to content

Replace std::generator with custom Generator for libc++ compatibility - #12

Open
Stevvven777 wants to merge 4 commits into
szdytom:mainfrom
Stevvven777:ios
Open

Replace std::generator with custom Generator for libc++ compatibility#12
Stevvven777 wants to merge 4 commits into
szdytom:mainfrom
Stevvven777:ios

Conversation

@Stevvven777

Copy link
Copy Markdown
Contributor

Problem

std::generator (P2502R2) is not yet implemented in libc++, which prevents building on macOS/Apple Clang.

  • libc++ C++23 status shows P2502R2 as unimplemented, even in LLVM 22
  • On macOS, SFML requires Clang, so GCC cannot be used as a workaround
  • This does not affect Windows (MSVC STL) or Linux (libstdc++ 14+)

Solution

Add a custom wf::Generator<T> in include/wforge/generator.h that replicates std::generator's coroutine-based API with identical co_yield/co_return semantics and range-based for loop support.

Key characteristics:

  • Returns const T& from operator* — zero-copy semantics matching std::generator
  • Single header, no external dependencies
  • Drop-in replaceable with std::generator when libc++ eventually supports it

Files changed:

  • New: include/wforge/generator.h — custom generator implementation
  • Modified: include/wforge/2d.h, include/wforge/assets.h, src/2d.cpp, src/font.cpp — replace std::generatorwf::Generator

…lity

std::generator (P2502R2) is not yet implemented in libc++, which prevents
building on macOS/Apple Clang. This adds a custom coroutine-based Generator
class with equivalent API and zero-copy reference semantics.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces usage of std::generator with a custom coroutine-based wf::Generator<T> to restore C++23 builds on libc++ (macOS/Apple Clang), where std::generator is not yet available.

Changes:

  • Added include/wforge/generator.h implementing wf::Generator<T> as a range-like coroutine type.
  • Updated 2D helper APIs (tilesOnSegment, neighbors4, neighbors8) to return wf::Generator instead of std::generator.
  • Updated PixelFont::textBitmap to return wf::Generator instead of std::generator.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
include/wforge/generator.h Introduces a custom coroutine generator type intended to replace std::generator on libc++.
include/wforge/2d.h Switches 2D generator-returning APIs to wf::Generator and updates includes accordingly.
include/wforge/assets.h Updates PixelFont::textBitmap declaration to return wf::Generator.
src/2d.cpp Updates implementations of tile/neighbor enumeration to return wf::Generator (and drops <generator>).
src/font.cpp Updates PixelFont::textBitmap definition to return wf::Generator.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +44
struct promise_type {
T current_value;

auto get_return_object() {
return Generator{handle_type::from_promise(*this)};
}

auto initial_suspend() noexcept {
return std::suspend_always{};
}

auto final_suspend() noexcept {
return std::suspend_always{};
}

auto yield_value(T value) noexcept {
current_value = std::move(value);
return std::suspend_always{};
}

void return_void() noexcept {}

void unhandled_exception() {
std::terminate();
}
Comment on lines +71 to +91
struct iterator {
handle_type _handle;

iterator &operator++() {
_handle.resume();
return *this;
}

const T &operator*() const noexcept {
return _handle.promise().current_value;
}

bool operator==(std::default_sentinel_t) const {
return !_handle || _handle.done();
}
};

iterator begin() {
_handle.resume();
return {_handle};
}
Comment on lines +4 to +7
#include <coroutine>
#include <exception>
#include <iterator>
#include <utility>
Comment thread include/wforge/2d.h
Comment on lines +4 to 6
#include "wforge/generator.h"
#include <array>
#include <generator>
#include <utility>
| Aspect | Before | After |
|--------|--------|-------|
| Value storage | Member T current_value | manual_lifetime union + placement new |
| Exception handling | std::terminate() | Store exception_ptr + rethrow |
| Lifetime tracking | None | _started flag |
| Incomplete destructor | No cleanup | Explicit destruct() to avoid leak |
| final_suspend | suspend_always{} | Custom final_awaiter (symmetric transfer) |
| iterator | Copyable, no typedefs | Move-only, full input_iterator typedefs |
| operator++(int) | Missing | Defined |
| operator* return | const T& | reference (value type for array<int,2>) |
| begin() guard | None | assert(_handle && !_started) |
| Exception check | None | Checked in begin() and operator++
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants