The standard says that <coroutine> should be present for freestanding.
That was intentionally left out of the initial implementation, but can
be done without much trouble. The header should be moved to libsupc++ at
some point in stage 1.
The standard also says that <coroutine> defines a std::hash
specialization, which was missing from our implementation. That's a
problem for freestanding (see LWG 3653) so only do that for hosted.
We can use concepts to constrain the __coroutine_traits_impl base class
when compiled with concepts enabled. In a pure C++20 implementation we
would not need that base class at all and could just use a constrained
partial specialization of coroutine_traits. But the absence of the
__coroutine_traits_impl<R, void> base would create an ABI difference
between the non-standard C++14/C++17 support for coroutines and the same
code compiled as C++20. If we drop support for <coroutine> pre-C++20 we
should revisit this.
libstdc++-v3/ChangeLog:
PR libstdc++/103726
* include/Makefile.am: Install <coroutine> for freestanding.
* include/Makefile.in: Regenerate.
* include/std/coroutine: Adjust headers and preprocessor
conditions.
(__coroutine_traits_impl): Use concepts when available.
[_GLIBCXX_HOSTED] (hash<coroutine_handle>): Define.
# This is a subset of the full install-headers rule. We only need <ciso646>,
# <cstddef>, <cfloat>, <limits>, <climits>, <version>, <cstdint>, <cstdlib>,
# <new>, <typeinfo>, <exception>, <initializer_list>, <cstdalign>, <cstdarg>,
-# <concepts>, <cstdbool>, <type_traits>, <bit>, <atomic>,
+# <concepts>, <coroutine>, <cstdbool>, <type_traits>, <bit>, <atomic>,
# and any files which they include (and which we provide).
# <new>, <typeinfo>, <exception>, <initializer_list> and <compare>
# are installed by libsupc++, so only the others and the sub-includes
${glibcxx_srcdir}/$(CPU_DEFINES_SRCDIR)/cpu_defines.h; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${host_installdir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${std_builddir}
- for file in limits type_traits atomic bit concepts version; do \
+ for file in limits type_traits atomic bit concepts coroutine version; do \
$(INSTALL_DATA) ${std_builddir}/$${file} $(DESTDIR)${gxx_include_dir}/${std_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir}
for file in ciso646 cstddef cfloat climits cstdint cstdlib \
# This is a subset of the full install-headers rule. We only need <ciso646>,
# <cstddef>, <cfloat>, <limits>, <climits>, <version>, <cstdint>, <cstdlib>,
# <new>, <typeinfo>, <exception>, <initializer_list>, <cstdalign>, <cstdarg>,
-# <concepts>, <cstdbool>, <type_traits>, <bit>, <atomic>,
+# <concepts>, <coroutine>, <cstdbool>, <type_traits>, <bit>, <atomic>,
# and any files which they include (and which we provide).
# <new>, <typeinfo>, <exception>, <initializer_list> and <compare>
# are installed by libsupc++, so only the others and the sub-includes
${glibcxx_srcdir}/$(CPU_DEFINES_SRCDIR)/cpu_defines.h; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${host_installdir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${std_builddir}
- for file in limits type_traits atomic bit concepts version; do \
+ for file in limits type_traits atomic bit concepts coroutine version; do \
$(INSTALL_DATA) ${std_builddir}/$${file} $(DESTDIR)${gxx_include_dir}/${std_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir}
for file in ciso646 cstddef cfloat climits cstdint cstdlib \
// It is very likely that earlier versions would work, but they are untested.
#if __cplusplus >= 201402L
-#include <bits/c++config.h>
+#include <type_traits>
+#if __cplusplus > 201703L
+# include <compare>
+#endif
+
+#if !defined __cpp_lib_three_way_comparison && _GLIBCXX_HOSTED
+# include <bits/stl_function.h> // for std::less
+#endif
/**
* @defgroup coroutines Coroutines
*
* Components for supporting coroutine implementations.
+ *
+ * @since C++20 (and since C++14 as a libstdc++ extension)
*/
-#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
-# include <compare>
-# define _COROUTINES_USE_SPACESHIP 1
-#else
-# include <bits/stl_function.h> // for std::less
-# define _COROUTINES_USE_SPACESHIP 0
-#endif
-
namespace std _GLIBCXX_VISIBILITY (default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
inline namespace __n4861 {
- // 17.12.2 coroutine traits
+ // C++20 17.12.2 coroutine traits
/// [coroutine.traits]
/// [coroutine.traits.primary]
/// If _Result::promise_type is valid and denotes a type then the traits
/// have a single publicly accessible member, otherwise they are empty.
+ template <typename _Result, typename... _ArgTypes>
+ struct coroutine_traits;
+
template <typename _Result, typename = void>
struct __coroutine_traits_impl {};
template <typename _Result>
+#if __cpp_concepts
+ requires requires { typename _Result::promise_type; }
+ struct __coroutine_traits_impl<_Result, void>
+#else
struct __coroutine_traits_impl<_Result,
- __void_t<typename _Result::promise_type>>
+ __void_t<typename _Result::promise_type>>
+#endif
{
using promise_type = typename _Result::promise_type;
};
- template <typename _Result, typename...>
+ template <typename _Result, typename... _ArgTypes>
struct coroutine_traits : __coroutine_traits_impl<_Result> {};
- // 17.12.3 Class template coroutine_handle
+ // C++20 17.12.3 Class template coroutine_handle
/// [coroutine.handle]
template <typename _Promise = void>
struct coroutine_handle;
return __a.address() == __b.address();
}
-#if _COROUTINES_USE_SPACESHIP
+#ifdef __cpp_lib_three_way_comparison
constexpr strong_ordering
operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
constexpr bool
operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
+#if _GLIBCXX_HOSTED
return less<void*>()(__a.address(), __b.address());
+#else
+ return (__UINTPTR_TYPE__)__a.address() < (__UINTPTR_TYPE__)__b.address();
+#endif
}
constexpr bool
} // namespace __n4861
+#if _GLIBCXX_HOSTED
+ template<typename _Tp> struct hash;
+
+ template<typename _Promise>
+ struct hash<coroutine_handle<_Promise>>
+ {
+ size_t
+ operator()(const coroutine_handle<_Promise>& __h) noexcept
+ {
+ return reinterpret_cast<size_t>(__h.address());
+ }
+ };
+#endif
+
#else
#error "the coroutine header requires -fcoroutines"
#endif