commit c7b591f3868f778ce89b14cbfb81d8e96d0daad2 Author: Jonathan Wakely Date: Fri Feb 7 20:28:06 2020 +0000 libstdc++: Add <=> to thread::id * include/std/thread (thread::id::operator<=>): Define for C++20. * testsuite/30_threads/thread/id/70294.cc: Do not take addresses of functions in namespace std. * testsuite/30_threads/thread/id/operators_c++20.cc: New test. diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index b533bca578f..1f9c13ff7d1 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -45,7 +45,8 @@ #include // std::tuple #if __cplusplus > 201703L -# include // std::stop_source, std::stop_token, std::nostopstate +# include // std::strong_ordering +# include // std::stop_source, std::stop_token, std::nostopstate #endif #ifdef _GLIBCXX_USE_NANOSLEEP @@ -96,17 +97,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: friend class thread; - friend class hash; + friend class hash; friend bool - operator==(thread::id __x, thread::id __y) noexcept; + operator==(id __x, id __y) noexcept; +#if __cpp_lib_three_way_comparison + friend strong_ordering + operator<=>(id __x, id __y) noexcept; +#else friend bool - operator<(thread::id __x, thread::id __y) noexcept; + operator<(id __x, id __y) noexcept; +#endif template friend basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id); + operator<<(basic_ostream<_CharT, _Traits>& __out, id __id); }; private: @@ -180,7 +186,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void detach(); - thread::id + id get_id() const noexcept { return _M_id; } @@ -296,6 +302,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __x._M_thread == __y._M_thread; } +#if __cpp_lib_three_way_comparison + inline strong_ordering + operator<=>(thread::id __x, thread::id __y) noexcept + { return __x._M_thread <=> __y._M_thread; } +#else inline bool operator!=(thread::id __x, thread::id __y) noexcept { return !(__x == __y); } @@ -319,6 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool operator>=(thread::id __x, thread::id __y) noexcept { return !(__x < __y); } +#endif // __cpp_lib_three_way_comparison // DR 889. /// std::hash specialization for thread::id. @@ -424,8 +436,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class jthread { public: - using id = std::thread::id; - using native_handle_type = std::thread::native_handle_type; + using id = thread::id; + using native_handle_type = thread::native_handle_type; jthread() noexcept : _M_stop_source{nostopstate} @@ -498,7 +510,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[nodiscard]] static unsigned hardware_concurrency() noexcept { - return std::thread::hardware_concurrency(); + return thread::hardware_concurrency(); } [[nodiscard]] stop_source @@ -544,7 +556,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } stop_source _M_stop_source; - std::thread _M_thread; + thread _M_thread; }; #endif // __cpp_lib_jthread _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/30_threads/thread/id/70294.cc b/libstdc++-v3/testsuite/30_threads/thread/id/70294.cc index ac3b58afa75..d9c61f74351 100644 --- a/libstdc++-v3/testsuite/30_threads/thread/id/70294.cc +++ b/libstdc++-v3/testsuite/30_threads/thread/id/70294.cc @@ -19,5 +19,14 @@ #include -bool (*lt)(std::thread::id, std::thread::id) = &std::operator<; -bool (*eq)(std::thread::id, std::thread::id) = &std::operator==; +struct T +{ + operator std::thread::id() const; +} const t; + +using namespace std; + +// std::thread::id comparison operators are not hidden friends, +// so should be candidates for these expressions: +bool lt = t < t; +bool eq = t == t; diff --git a/libstdc++-v3/testsuite/30_threads/thread/id/operators.cc b/libstdc++-v3/testsuite/30_threads/thread/id/operators.cc index fb6440bfc3d..3d84afafd15 100644 --- a/libstdc++-v3/testsuite/30_threads/thread/id/operators.cc +++ b/libstdc++-v3/testsuite/30_threads/thread/id/operators.cc @@ -20,16 +20,26 @@ #include +template + struct check_type + : std::false_type + { }; + +template + struct check_type + : std::true_type + { }; + void test01() { // thread::id operators std::thread::id id1; std::thread::id id2; - id1 == id2; - id1 != id2; - id1 < id2; - id1 > id2; - id1 >= id2; - id1 <= id2; + static_assert( check_type{} ); + static_assert( check_type{} ); + static_assert( check_type{} ); + static_assert( check_type id2)>{} ); + static_assert( check_type= id2)>{} ); + static_assert( check_type{} ); } diff --git a/libstdc++-v3/testsuite/30_threads/thread/id/operators_c++20.cc b/libstdc++-v3/testsuite/30_threads/thread/id/operators_c++20.cc new file mode 100644 index 00000000000..6094b0e1501 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/thread/id/operators_c++20.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// { dg-require-gthreads "" } + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +template + struct check_type + : std::false_type + { }; + +template + struct check_type + : std::true_type + { }; + +void test01() +{ + // thread::id operators + std::thread::id id1; + std::thread::id id2; + + static_assert( check_type{} ); + static_assert( check_type{} ); + static_assert( check_type{} ); + static_assert( check_type id2)>{} ); + static_assert( check_type= id2)>{} ); + static_assert( check_type{} ); + + static_assert( check_type id2)>{} ); +}