aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.generator/generator_promise.ccm
blob: 3e8aa8cde9c530201f137c0936c69c2b2d0c5205 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
///////////////////////////////////////////////////////////////////////////////
// Reference implementation of std::generator proposal P2168.
//
// See https://wg21.link/P2168 for details.
//
///////////////////////////////////////////////////////////////////////////////
// Copyright Lewis Baker, Corentin Jabot
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0.
// (See accompanying file LICENSE or http://www.boost.org/LICENSE_1_0.txt)
///////////////////////////////////////////////////////////////////////////////

export module nihil.generator:generator_promise;

import nihil.std;
import :forward;
import :generator_promise_base;
import :promise_base_alloc;

namespace nihil {

export template <typename Generator, typename ByteAllocator, bool ExplicitAllocator = false>
struct generator_promise;

export template <typename Ref, typename Value, typename Alloc, typename ByteAllocator,
          bool ExplicitAllocator>
struct generator_promise<generator<Ref, Value, Alloc>, ByteAllocator, ExplicitAllocator> final
	: public generator_promise_base<Ref>,
	  public promise_base_alloc<ByteAllocator>
{
	generator_promise() noexcept
		: generator_promise_base<Ref>(
			  std::coroutine_handle<generator_promise>::from_promise(*this))
	{
	}

	auto get_return_object() noexcept -> generator<Ref, Value, Alloc>
	{
		return generator<Ref, Value, Alloc>{
			std::coroutine_handle<generator_promise>::from_promise(*this)};
	}

	using generator_promise_base<Ref>::yield_value;

	template <std::ranges::range Rng>
	auto yield_value(nihil::elements_of<Rng> &&x) -> typename generator_promise_base<
		Ref>::template yield_sequence_awaiter<generator<Ref, Value, Alloc>>
	{
		static_assert(!ExplicitAllocator,
		              "This coroutine has an explicit allocator specified with "
		              "std::allocator_arg so an allocator needs to be passed "
		              "explicitely to std::elements_of");
		return [](auto &&rng) -> generator<Ref, Value, Alloc> {
			for (auto &&e : rng)
				co_yield static_cast<decltype(e)>(e);
		}(std::forward<Rng>(x.get()));
	}
};

} // namespace nihil