Skip to content

Commit 866336b

Browse files
committed
give up trying to use std::vector in constant evaluation
1 parent ebcaaba commit 866336b

3 files changed

Lines changed: 114 additions & 50 deletions

File tree

include/stdexec/__detail/__completion_info.hpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include <array>
3131
#include <compare>
3232
#include <span>
33-
#include <vector>
3433
// IWYU pragma: end_keep
3534

3635
namespace STDEXEC
@@ -145,15 +144,5 @@ namespace STDEXEC
145144
std::ranges::sort(__compls);
146145
return __compls;
147146
}
148-
149-
template <class _Ty>
150-
constexpr auto __append_range(std::vector<_Ty> &__dst, std::span<_Ty const> __src)
151-
{
152-
#if __cpp_lib_containers_ranges >= 202202L
153-
__dst.append_range(__src);
154-
#else
155-
__dst.insert(__dst.end(), __src.begin(), __src.end());
156-
#endif
157-
}
158147
} // namespace __cmplsigs
159148
} // namespace STDEXEC

include/stdexec/__detail/__let.hpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,6 @@ namespace STDEXEC
522522
{
523523
private:
524524
using __set_t = __t<_LetTag>;
525-
using __cmpl_vec_t = std::vector<__completion_info>;
526525
using __eptr_sig_t = set_error_t(std::exception_ptr);
527526

528527
template <class _CvSender>
@@ -543,8 +542,8 @@ namespace STDEXEC
543542
__mbind_front_q<__opstate, __set_t, __child_of<_CvSender>, __fn_t<_CvSender>, _Receiver>>;
544543

545544
template <class _Fun, class _Child, class... _Env>
546-
static constexpr auto __transform_cmplsig = //
547-
[]<class... _As>(__set_t (*)(_As...), __completion_info __info, __cmpl_vec_t& __out) //
545+
static constexpr auto __transform_cmplsig = //
546+
[]<class... _As>(__set_t (*)(_As...), __completion_info __info) //
548547
-> decltype(auto)
549548
{
550549
if constexpr (!__decay_copyable<_As...>)
@@ -571,34 +570,30 @@ namespace STDEXEC
571570
STDEXEC_TRY_LET(constexpr auto __cmpls,
572571
STDEXEC::__get_completion_info<__sndr2_t, __env2_t<_Child, _Env>...>())
573572
{
574-
__cmplsigs::__append_range(__out, std::span{__cmpls});
575-
576573
if constexpr (!__nothrow_decay_copyable<_As...>
577574
|| !__nothrow_invocable<_Fun, __decay_t<_As>&...>
578575
|| (!__nothrow_connectable<__sndr2_t, __rcvr2_t<_Child, _Env>> || ...))
579576
{
580-
__out.emplace_back(__signature<__eptr_sig_t>, __info.__domain, __info.__behavior);
577+
__completion_info const __eptr_info(__signature<__eptr_sig_t>,
578+
__info.__domain,
579+
__info.__behavior);
580+
return __cmpls + __static_vector{__eptr_info};
581+
}
582+
else
583+
{
584+
return __cmpls;
581585
}
582-
583-
return (__out);
584586
}
585587
}
586588
};
587589

588590
template <__completion_info _Info>
589-
static constexpr auto __maybe_transform_cmplsig =
590-
[](auto __transform, __cmpl_vec_t& __out) -> decltype(auto)
591+
static constexpr auto __maybe_transform_cmplsig = [](auto __transform) -> decltype(auto)
591592
{
592593
if constexpr (_Info.__disposition != __set_t::__disposition)
593-
{
594-
__out.push_back(_Info);
595-
return (__out);
596-
}
594+
return __static_vector{_Info};
597595
else
598-
{
599-
using __sig_t = __mtypeof<_Info.__signature>;
600-
return __transform(__signature<__sig_t>, _Info, __out);
601-
}
596+
return __transform(__signature<__mtypeof<_Info.__signature>>, _Info);
602597
};
603598

604599
//! @tparam _Info A `__static_vector` of `__completion_info` objects representing
@@ -608,10 +603,10 @@ namespace STDEXEC
608603
{
609604
return []
610605
{
611-
std::vector<__completion_info> __result;
612-
// NB: this fold uses an overloaded comma operator that propagates __mexception
613-
// objects when constexpr exceptions are not available.
614-
return (__maybe_transform_cmplsig<_Info[_Is]>(_Transform, __result), ..., __result);
606+
__static_vector<__completion_info, 0> __result;
607+
// NB: this fold uses an overloaded addition operator that propagates
608+
// __mexception objects when constexpr exceptions are not available.
609+
return (__maybe_transform_cmplsig<_Info[_Is]>(_Transform) + ... + __result);
615610
};
616611
};
617612

include/stdexec/__detail/__static_vector.hpp

Lines changed: 97 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,48 @@
2525

2626
namespace STDEXEC
2727
{
28-
template <class _Tp, std::size_t _Size>
29-
struct __static_vector
28+
template <class _Tp, std::size_t _Capacity>
29+
struct __static_vector;
30+
31+
namespace __detail
32+
{
33+
struct __static_vector_base
34+
{
35+
template <class... _What, class _Tp, std::size_t _Capacity>
36+
[[nodiscard]]
37+
friend constexpr auto operator+(__mexception<_What...>, //
38+
__static_vector<_Tp, _Capacity> const &) noexcept //
39+
-> __mexception<_What...>
40+
{
41+
return {};
42+
}
43+
44+
template <class... _What, class _Tp, std::size_t _Capacity>
45+
[[nodiscard]]
46+
friend constexpr auto operator+(__static_vector<_Tp, _Capacity> const &, //
47+
__mexception<_What...>) noexcept //
48+
-> __mexception<_What...>
49+
{
50+
return {};
51+
}
52+
53+
template <class _Ty, std::size_t _Capacity0, std::size_t _Capacity1>
54+
[[nodiscard]]
55+
friend constexpr auto operator+(__static_vector<_Ty, _Capacity0> const &__lhs, //
56+
__static_vector<_Ty, _Capacity1> const &__rhs)
57+
noexcept(__nothrow_copy_constructible<_Ty>) -> __static_vector<_Ty, _Capacity0 + _Capacity1>
58+
{
59+
__static_vector<_Ty, _Capacity0 + _Capacity1> __result;
60+
std::copy(__lhs.begin(), __lhs.end(), __result.begin());
61+
std::copy(__rhs.begin(), __rhs.end(), __result.begin() + __lhs.size());
62+
__result.resize(__lhs.size() + __rhs.size());
63+
return __result;
64+
}
65+
};
66+
} // namespace __detail
67+
68+
template <class _Tp, std::size_t _Capacity>
69+
struct __static_vector : __detail::__static_vector_base
3070
{
3171
using value_type = _Tp;
3272
using iterator = value_type *;
@@ -37,8 +77,9 @@ namespace STDEXEC
3777
constexpr __static_vector(std::initializer_list<value_type> __init)
3878
noexcept(__nothrow_copy_constructible<value_type>)
3979
{
40-
auto const __end = std::copy_n(__init.begin(), (std::min) (__init.size(), _Size), __data_);
41-
__size_ = __end - __data_;
80+
auto const __count = (std::min) (__init.size(), _Capacity);
81+
auto const __end = std::ranges::copy_n(__init.begin(), __count, __data_).out;
82+
__size_ = __end - __data_;
4283
}
4384

4485
[[nodiscard]]
@@ -86,7 +127,7 @@ namespace STDEXEC
86127
[[nodiscard]]
87128
static constexpr auto capacity() noexcept -> std::size_t
88129
{
89-
return _Size;
130+
return _Capacity;
90131
}
91132

92133
constexpr void resize(std::size_t __new_size) noexcept
@@ -102,19 +143,58 @@ namespace STDEXEC
102143
}
103144

104145
std::size_t __size_ = 0;
105-
value_type __data_[_Size];
146+
value_type __data_[_Capacity];
106147
};
107148

108-
template <class _Tp, std::size_t _Size0, std::size_t _Size1>
109-
[[nodiscard]]
110-
constexpr auto __concat(__static_vector<_Tp, _Size0> const &__lhs, //
111-
__static_vector<_Tp, _Size1> const &__rhs)
112-
noexcept(__nothrow_copy_constructible<_Tp>) -> __static_vector<_Tp, _Size0 + _Size1>
149+
// Specialization of __static_vector for zero capacity that doesn't require default
150+
// constructibility of _Tp.
151+
template <class _Tp>
152+
struct __static_vector<_Tp, 0> : __detail::__static_vector_base
113153
{
114-
__static_vector<_Tp, _Size0 + _Size1> __result;
115-
std::copy(__lhs.begin(), __lhs.end(), __result.begin());
116-
std::copy(__rhs.begin(), __rhs.end(), __result.begin() + __lhs.size());
117-
__result.resize(__lhs.size() + __rhs.size());
118-
return __result;
119-
}
154+
using value_type = _Tp;
155+
using iterator = value_type *;
156+
using const_iterator = value_type const *;
157+
158+
__static_vector() = default;
159+
160+
[[nodiscard]]
161+
constexpr auto begin() noexcept -> iterator
162+
{
163+
return nullptr;
164+
}
165+
166+
[[nodiscard]]
167+
constexpr auto begin() const noexcept -> const_iterator
168+
{
169+
return nullptr;
170+
}
171+
172+
[[nodiscard]]
173+
constexpr auto end() noexcept -> iterator
174+
{
175+
return nullptr;
176+
}
177+
178+
[[nodiscard]]
179+
constexpr auto end() const noexcept -> const_iterator
180+
{
181+
return nullptr;
182+
}
183+
184+
[[nodiscard]]
185+
static constexpr auto size() noexcept -> std::size_t
186+
{
187+
return 0;
188+
}
189+
190+
[[nodiscard]]
191+
static constexpr auto capacity() noexcept -> std::size_t
192+
{
193+
return 0;
194+
}
195+
};
196+
197+
template <class _First, __same_as<_First>... _Rest>
198+
STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
199+
__static_vector(_First, _Rest...) -> __static_vector<_First, 1 + sizeof...(_Rest)>;
120200
} // namespace STDEXEC

0 commit comments

Comments
 (0)