Fix a recursive template instantiation issue on clang and gcc

This commit is contained in:
Denis Blank 2018-12-10 05:08:39 +01:00
parent 1320c8eb63
commit 57bb43138b
3 changed files with 23 additions and 22 deletions

View File

@ -119,13 +119,14 @@ public:
/// Constructor accepting any object convertible to the data object,
/// while erasing the annotation
template <typename OData,
template <typename OtherData,
std::enable_if_t<detail::base::can_accept_continuation<
Data, Annotation, detail::traits::unrefcv_t<OData>>::value>* =
nullptr>
continuable_base(OData&& data) // NOLINT(misc-forwarding-reference-overload)
: data_(detail::base::proxy_continuable<Annotation, OData>(
std::forward<OData>(data))) {
Data, Annotation,
detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>
continuable_base(OtherData&& data)
: data_(detail::base::proxy_continuable<
Annotation, detail::traits::unrefcv_t<OtherData>>(
std::forward<OtherData>(data))) {
}
/// Constructor taking the data of other continuable_base objects

View File

@ -134,7 +134,6 @@ struct proxy_continuable<traits::identity<Args...>, Continuation>
proxy_continuable& operator=(proxy_continuable&&) = default;
proxy_continuable& operator=(proxy_continuable const&) = delete;
using Continuation::Continuation;
using Continuation::operator();
bool operator()(is_ready_arg_t) const noexcept {
@ -154,7 +153,7 @@ struct attorney {
util::ownership ownership) {
using continuation_t = continuable_base<traits::unrefcv_t<T>, //
traits::unrefcv_t<Annotation>>;
return continuation_t({std::forward<T>(continuation)}, ownership);
return continuation_t{std::forward<T>(continuation), ownership};
}
/// Creates a continuable_base from the given continuation,
@ -165,8 +164,8 @@ struct attorney {
static auto create_from(T&& continuation, Hint, util::ownership ownership) {
using hint_t = traits::unrefcv_t<Hint>;
using proxy_t = proxy_continuable<hint_t, traits::unrefcv_t<T>>;
return continuable_base<proxy_t, hint_t>(
proxy_t{std::forward<T>(continuation)}, ownership);
return continuable_base<proxy_t, hint_t>{
proxy_t{std::forward<T>(continuation)}, ownership};
}
/// Returns the ownership of the given continuable_base
@ -873,20 +872,15 @@ void finalize_continuation(Continuation&& continuation) {
/// Deduces to a true type if the given callable data can be wrapped
/// with the given hint and converted to the given Data.
template <typename Data, typename Annotation, typename Continuation,
typename = void>
template <typename Data, typename Annotation, typename Continuation>
struct can_accept_continuation : std::false_type {};
template <typename Data, typename... Args, typename Continuation>
struct can_accept_continuation<
Data, traits::identity<Args...>, Continuation,
traits::void_t<
std::enable_if_t<traits::is_invocable<
Continuation, callbacks::final_callback>::value>,
std::enable_if_t<std::is_convertible<
proxy_continuable<traits::identity<Args...>, Continuation>,
Data>::value>>> : std::true_type
{};
struct can_accept_continuation<Data, traits::identity<Args...>, Continuation>
: traits::conjunction<
traits::is_invocable<Continuation, callbacks::final_callback>,
std::is_convertible<
proxy_continuable<traits::identity<Args...>, Continuation>,
Data>> {};
/// Workaround for GCC bug:
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095

View File

@ -43,3 +43,9 @@ TEST(regression_tests, are_multiple_args_mergeable) {
tp2);
EXPECT_EQ(count, 20);
}
/// Recursive instantiation issue which affects Clang and GCC
TEST(regression_tests, are_erasures_direct_chainable) {
continuable<>(make_ready_continuable())
.then(continuable<>(make_ready_continuable()));
}