2018-05-03 Jonathan Wakely <jwakely@redhat.com>
+ PR libstdc++/84535
+ * include/std/thread (thread::__not_same): New SFINAE helper.
+ (thread::thread(_Callable&&, _Args&&...)): Add SFINAE constraint that
+ first argument is not a std::thread. Add static assertion to check
+ INVOKE expression is valid.
+ (thread::thread(thread&), thread::thread(const thread&&)): Remove.
+ (thread::_Invoke::_M_invoke, thread::_Invoke::operator()): Use
+ __invoke_result for return types and remove exception specifications.
+ * testsuite/30_threads/thread/cons/84535.cc: New.
+
* include/std/future (__async_result_of): Use __invoke_result instead
of result_of.
private:
id _M_id;
- public:
- thread() noexcept = default;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2097. packaged_task constructors should be constrained
- thread(thread&) = delete;
- thread(const thread&) = delete;
- thread(const thread&&) = delete;
+ template<typename _Tp>
+ using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>;
- thread(thread&& __t) noexcept
- { swap(__t); }
+ public:
+ thread() noexcept = default;
- template<typename _Callable, typename... _Args>
+ template<typename _Callable, typename... _Args,
+ typename = _Require<__not_same<_Callable>>>
explicit
thread(_Callable&& __f, _Args&&... __args)
{
+ static_assert( __is_invocable<typename decay<_Callable>::type,
+ typename decay<_Args>::type...>::value,
+ "std::thread arguments must be invocable after conversion to rvalues"
+ );
+
#ifdef GTHR_ACTIVE_PROXY
// Create a reference to pthread_create, not just the gthr weak symbol.
auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
std::terminate();
}
+ thread(const thread&) = delete;
+
+ thread(thread&& __t) noexcept
+ { swap(__t); }
+
thread& operator=(const thread&) = delete;
thread& operator=(thread&& __t) noexcept
{
_Tuple _M_t;
- template<size_t _Index>
- static __tuple_element_t<_Index, _Tuple>&&
- _S_declval();
+ template<typename>
+ struct __result;
+ template<typename _Fn, typename... _Args>
+ struct __result<tuple<_Fn, _Args...>>
+ : __invoke_result<_Fn, _Args...>
+ { };
template<size_t... _Ind>
- auto
+ typename __result<_Tuple>::type
_M_invoke(_Index_tuple<_Ind...>)
- noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
- -> decltype(std::__invoke(_S_declval<_Ind>()...))
{ return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
- using _Indices
- = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
-
- auto
+ typename __result<_Tuple>::type
operator()()
- noexcept(noexcept(std::declval<_Invoker&>()._M_invoke(_Indices())))
- -> decltype(std::declval<_Invoker&>()._M_invoke(_Indices()))
- { return _M_invoke(_Indices()); }
+ {
+ using _Indices
+ = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
+ return _M_invoke(_Indices());
+ }
};
template<typename... _Tp>
- using __decayed_tuple = tuple<typename std::decay<_Tp>::type...>;
+ using __decayed_tuple = tuple<typename decay<_Tp>::type...>;
public:
// Returns a call wrapper that stores
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2018 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
+// <http://www.gnu.org/licenses/>.
+
+#include <thread>
+
+using std::is_constructible;
+using std::thread;
+
+// PR libstdc++/84535
+static_assert(!is_constructible<thread, thread, int>::value, "");
+static_assert(!is_constructible<thread, thread&, int>::value, "");
+static_assert(!is_constructible<thread, const thread&, int>::value, "");
+static_assert(!is_constructible<thread, const thread&&, int>::value, "");