Commit 1b3fad81 by Jonathan Wakely Committed by Jonathan Wakely

re PR libstdc++/45893 ([C++0x] [DR 817] Finish updating std::bind to rvalue refs)

2010-10-08  Jonathan Wakely  <jwakely.gcc@gmail.com>

	PR libstdc++/45893
	* include/std/functional (bind): Implement DR 817 and add support
	for volatile-qualified call wrappers.
	* include/std/mutex (call_once): Implement DR 891.
	* include/std/thread (thread::thread): Implement DR 929.
	* include/std/future: Optimise use of std::bind.
	* testsuite/20_util/bind/cv_quals.cc: Test volatile-qualification.
	* testsuite/20_util/bind/move.cc: New.

From-SVN: r165144
parent 65d09bfe
2010-10-08 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/45893
* include/std/functional (bind): Implement DR 817 and add support
for volatile-qualified call wrappers.
* include/std/mutex (call_once): Implement DR 891.
* include/std/thread (thread::thread): Implement DR 929.
* include/std/future: Optimise use of std::bind.
* testsuite/20_util/bind/cv_quals.cc: Test volatile-qualification.
* testsuite/20_util/bind/move.cc: New.
2010-10-07 Hans-Peter Nilsson <hp@axis.com> 2010-10-07 Hans-Peter Nilsson <hp@axis.com>
PR libstdc++/45841 PR libstdc++/45841
......
...@@ -957,7 +957,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -957,7 +957,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
*/ */
template<typename _CVRef, typename _Tuple> template<typename _CVRef, typename _Tuple>
result_type result_type
operator()(_CVRef& __arg, _Tuple&&) const volatile operator()(_CVRef& __arg, _Tuple&) const volatile
{ return __arg.get(); } { return __arg.get(); }
}; };
...@@ -970,33 +970,26 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -970,33 +970,26 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
class _Mu<_Arg, true, false> class _Mu<_Arg, true, false>
{ {
public: public:
template<typename _Signature> class result;
// Determine the result type when we pass the arguments along. This
// involves passing along the cv-qualifiers placed on _Mu and
// unwrapping the argument bundle.
template<typename _CVMu, typename _CVArg, typename... _Args>
class result<_CVMu(_CVArg, tuple<_Args...>)>
: public result_of<_CVArg(_Args...)> { };
template<typename _CVArg, typename... _Args> template<typename _CVArg, typename... _Args>
typename result_of<_CVArg(_Args...)>::type auto
operator()(_CVArg& __arg, operator()(_CVArg& __arg,
tuple<_Args...>&& __tuple) const volatile tuple<_Args...>& __tuple) const volatile
-> decltype(__arg(declval<_Args>()...))
{ {
// Construct an index tuple and forward to __call // Construct an index tuple and forward to __call
typedef typename _Build_index_tuple<sizeof...(_Args)>::__type typedef typename _Build_index_tuple<sizeof...(_Args)>::__type
_Indexes; _Indexes;
return this->__call(__arg, std::move(__tuple), _Indexes()); return this->__call(__arg, __tuple, _Indexes());
} }
private: private:
// Invokes the underlying function object __arg by unpacking all // Invokes the underlying function object __arg by unpacking all
// of the arguments in the tuple. // of the arguments in the tuple.
template<typename _CVArg, typename... _Args, int... _Indexes> template<typename _CVArg, typename... _Args, int... _Indexes>
typename result_of<_CVArg(_Args...)>::type auto
__call(_CVArg& __arg, tuple<_Args...>&& __tuple, __call(_CVArg& __arg, tuple<_Args...>& __tuple,
const _Index_tuple<_Indexes...>&) const volatile const _Index_tuple<_Indexes...>&) const volatile
-> decltype(__arg(declval<_Args>()...))
{ {
return __arg(std::forward<_Args>(get<_Indexes>(__tuple))...); return __arg(std::forward<_Args>(get<_Indexes>(__tuple))...);
} }
...@@ -1029,7 +1022,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1029,7 +1022,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<typename _Tuple> template<typename _Tuple>
typename result<_Mu(_Arg, _Tuple)>::type typename result<_Mu(_Arg, _Tuple)>::type
operator()(const volatile _Arg&, _Tuple&& __tuple) const volatile operator()(const volatile _Arg&, _Tuple& __tuple) const volatile
{ {
return std::forward<typename result<_Mu(_Arg, _Tuple)>::type>( return std::forward<typename result<_Mu(_Arg, _Tuple)>::type>(
::std::get<(is_placeholder<_Arg>::value - 1)>(__tuple)); ::std::get<(is_placeholder<_Arg>::value - 1)>(__tuple));
...@@ -1056,7 +1049,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1056,7 +1049,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
// Pick up the cv-qualifiers of the argument // Pick up the cv-qualifiers of the argument
template<typename _CVArg, typename _Tuple> template<typename _CVArg, typename _Tuple>
_CVArg&& _CVArg&&
operator()(_CVArg&& __arg, _Tuple&&) const volatile operator()(_CVArg&& __arg, _Tuple&) const volatile
{ return std::forward<_CVArg>(__arg); } { return std::forward<_CVArg>(__arg); }
}; };
...@@ -1069,10 +1062,14 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1069,10 +1062,14 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
struct _Maybe_wrap_member_pointer struct _Maybe_wrap_member_pointer
{ {
typedef _Tp type; typedef _Tp type;
static const _Tp& static const _Tp&
__do_wrap(const _Tp& __x) __do_wrap(const _Tp& __x)
{ return __x; } { return __x; }
static _Tp&&
__do_wrap(_Tp&& __x)
{ return static_cast<_Tp&&>(__x); }
}; };
/** /**
...@@ -1100,6 +1097,20 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1100,6 +1097,20 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typedef void type; typedef void type;
}; };
// std::get<I> for volatile-qualified tuples
template<size_t _Ind, typename... _Tp>
inline auto
__volget(volatile tuple<_Tp...>& __tuple)
-> typename tuple_element<_Ind, tuple<_Tp...>>::type volatile&
{ return std::get<_Ind>(const_cast<tuple<_Tp...>&>(__tuple)); }
// std::get<I> for const-volatile-qualified tuples
template<size_t _Ind, typename... _Tp>
inline auto
__volget(const volatile tuple<_Tp...>& __tuple)
-> typename tuple_element<_Ind, tuple<_Tp...>>::type const volatile&
{ return std::get<_Ind>(const_cast<const tuple<_Tp...>&>(__tuple)); }
/// Type of the function object returned from bind(). /// Type of the function object returned from bind().
template<typename _Signature> template<typename _Signature>
struct _Bind; struct _Bind;
...@@ -1109,7 +1120,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1109,7 +1120,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
: public _Weak_result_type<_Functor> : public _Weak_result_type<_Functor>
{ {
typedef _Bind __self_type; typedef _Bind __self_type;
typedef typename _Build_index_tuple<sizeof...(_Bound_args)>::__type typedef typename _Build_index_tuple<sizeof...(_Bound_args)>::__type
_Bound_indexes; _Bound_indexes;
_Functor _M_f; _Functor _M_f;
...@@ -1121,7 +1132,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1121,7 +1132,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const // Call as const
...@@ -1130,10 +1141,9 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1130,10 +1141,9 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
__call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (get<_Indexes>(_M_bound_args), __args)...);
} }
#if 0
// Call as volatile // Call as volatile
template<typename _Result, typename... _Args, int... _Indexes> template<typename _Result, typename... _Args, int... _Indexes>
_Result _Result
...@@ -1141,7 +1151,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1141,7 +1151,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
_Index_tuple<_Indexes...>) volatile _Index_tuple<_Indexes...>) volatile
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const volatile // Call as const volatile
...@@ -1151,69 +1161,77 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1151,69 +1161,77 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
_Index_tuple<_Indexes...>) const volatile _Index_tuple<_Indexes...>) const volatile
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
#endif
public: public:
explicit _Bind(_Functor __f, _Bound_args... __bound_args) template<typename... _Args>
: _M_f(std::forward<_Functor>(__f)), explicit _Bind(const _Functor& __f, _Args&&... __args)
_M_bound_args(std::forward<_Bound_args>(__bound_args)...) : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...)
{ }
template<typename... _Args>
explicit _Bind(_Functor&& __f, _Args&&... __args)
: _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...)
{ }
_Bind(const _Bind&) = default;
_Bind(_Bind&& __b)
: _M_f(std::move(__b._M_f)), _M_bound_args(std::move(__b._M_bound_args))
{ } { }
// Call unqualified // Call unqualified
template<typename... _Args, typename _Result template<typename... _Args, typename _Result
= decltype( std::declval<_Functor>()( = decltype( std::declval<_Functor>()(
_Mu<_Bound_args>()( std::declval<_Bound_args&>(), _Mu<_Bound_args>()( std::declval<_Bound_args&>(),
std::declval<tuple<_Args...>&&>() )... ) )> std::declval<tuple<_Args...>&>() )... ) )>
_Result _Result
operator()(_Args&&... __args) operator()(_Args&&... __args)
{ {
return this->__call<_Result>(tuple<_Args...> return this->__call<_Result>(
(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
// Call as const // Call as const
template<typename... _Args, typename _Result template<typename... _Args, typename _Result
= decltype( std::declval<const _Functor>()( = decltype( std::declval<const _Functor>()(
_Mu<_Bound_args>()( std::declval<const _Bound_args&>(), _Mu<_Bound_args>()( std::declval<const _Bound_args&>(),
std::declval<tuple<_Args...>&&>() )... ) )> std::declval<tuple<_Args...>&>() )... ) )>
_Result _Result
operator()(_Args&&... __args) const operator()(_Args&&... __args) const
{ {
return this->__call_c<_Result>(tuple<_Args...> return this->__call_c<_Result>(
(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
#if 0
// Call as volatile // Call as volatile
template<typename... _Args, typename _Result template<typename... _Args, typename _Result
= decltype( std::declval<volatile _Functor>()( = decltype( std::declval<volatile _Functor>()(
_Mu<_Bound_args>()( std::declval<volatile _Bound_args&>(), _Mu<_Bound_args>()( std::declval<volatile _Bound_args&>(),
std::declval<tuple<_Args...>&&>() )... ) )> std::declval<tuple<_Args...>&>() )... ) )>
_Result _Result
operator()(_Args&&... __args) volatile operator()(_Args&&... __args) volatile
{ {
return this->__call_v<_Result>(tuple<_Args...> return this->__call_v<_Result>(
(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
// Call as const volatile // Call as const volatile
template<typename... _Args, typename _Result template<typename... _Args, typename _Result
= decltype( std::declval<const volatile _Functor>()( = decltype( std::declval<const volatile _Functor>()(
_Mu<_Bound_args>()( std::declval<const volatile _Bound_args&>(), _Mu<_Bound_args>()( std::declval<const volatile _Bound_args&>(),
std::declval<tuple<_Args...>&&>() )... ) )> std::declval<tuple<_Args...>&>() )... ) )>
_Result _Result
operator()(_Args&&... __args) const volatile operator()(_Args&&... __args) const volatile
{ {
return this->__call_c_v<_Result>(tuple<_Args...> return this->__call_c_v<_Result>(
(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
#endif
}; };
/// Type of the function object returned from bind<R>(). /// Type of the function object returned from bind<R>().
...@@ -1243,7 +1261,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1243,7 +1261,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __disable_if_void<_Res>::type = 0) typename __disable_if_void<_Res>::type = 0)
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call unqualified, return void // Call unqualified, return void
...@@ -1253,7 +1271,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1253,7 +1271,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __enable_if_void<_Res>::type = 0) typename __enable_if_void<_Res>::type = 0)
{ {
_M_f(_Mu<_Bound_args>() _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const // Call as const
...@@ -1263,7 +1281,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1263,7 +1281,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __disable_if_void<_Res>::type = 0) const typename __disable_if_void<_Res>::type = 0) const
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const, return void // Call as const, return void
...@@ -1273,7 +1291,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1273,7 +1291,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __enable_if_void<_Res>::type = 0) const typename __enable_if_void<_Res>::type = 0) const
{ {
_M_f(_Mu<_Bound_args>() _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as volatile // Call as volatile
...@@ -1283,7 +1301,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1283,7 +1301,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __disable_if_void<_Res>::type = 0) volatile typename __disable_if_void<_Res>::type = 0) volatile
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
// Call as volatile, return void // Call as volatile, return void
...@@ -1293,7 +1311,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1293,7 +1311,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __enable_if_void<_Res>::type = 0) volatile typename __enable_if_void<_Res>::type = 0) volatile
{ {
_M_f(_Mu<_Bound_args>() _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const volatile // Call as const volatile
...@@ -1303,7 +1321,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1303,7 +1321,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __disable_if_void<_Res>::type = 0) const volatile typename __disable_if_void<_Res>::type = 0) const volatile
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const volatile, return void // Call as const volatile, return void
...@@ -1314,16 +1332,26 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1314,16 +1332,26 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __enable_if_void<_Res>::type = 0) const volatile typename __enable_if_void<_Res>::type = 0) const volatile
{ {
_M_f(_Mu<_Bound_args>() _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), std::move(__args))...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
public: public:
typedef _Result result_type; typedef _Result result_type;
explicit template<typename... _Args>
_Bind_result(_Functor __f, _Bound_args... __bound_args) explicit _Bind_result(const _Functor& __f, _Args&&... __args)
: _M_f(std::forward<_Functor>(__f)), : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...)
_M_bound_args(std::forward<_Bound_args>(__bound_args)...) { }
template<typename... _Args>
explicit _Bind_result(_Functor&& __f, _Args&&... __args)
: _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...)
{ }
_Bind_result(const _Bind_result&) = default;
_Bind_result(_Bind_result&& __b)
: _M_f(std::move(__b._M_f)), _M_bound_args(std::move(__b._M_bound_args))
{ } { }
// Call unqualified // Call unqualified
...@@ -1332,7 +1360,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1332,7 +1360,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
operator()(_Args&&... __args) operator()(_Args&&... __args)
{ {
return this->__call<_Result>( return this->__call<_Result>(
tuple<_Args...>(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
...@@ -1342,7 +1370,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1342,7 +1370,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
operator()(_Args&&... __args) const operator()(_Args&&... __args) const
{ {
return this->__call<_Result>( return this->__call<_Result>(
tuple<_Args...>(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
...@@ -1352,7 +1380,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1352,7 +1380,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
operator()(_Args&&... __args) volatile operator()(_Args&&... __args) volatile
{ {
return this->__call<_Result>( return this->__call<_Result>(
tuple<_Args...>(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
...@@ -1362,7 +1390,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1362,7 +1390,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
operator()(_Args&&... __args) const volatile operator()(_Args&&... __args) const volatile
{ {
return this->__call<_Result>( return this->__call<_Result>(
tuple<_Args...>(std::forward<_Args>(__args)...), std::forward_as_tuple(std::forward<_Args>(__args)...),
_Bound_indexes()); _Bound_indexes());
} }
}; };
...@@ -1383,38 +1411,55 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) ...@@ -1383,38 +1411,55 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
struct is_bind_expression<_Bind_result<_Result, _Signature> > struct is_bind_expression<_Bind_result<_Result, _Signature> >
: public true_type { }; : public true_type { };
template<typename _Functor, typename... _ArgTypes>
struct _Bind_helper
{
typedef _Maybe_wrap_member_pointer<typename decay<_Functor>::type>
__maybe_type;
typedef typename __maybe_type::type __functor_type;
typedef _Bind<__functor_type(typename decay<_ArgTypes>::type...)> type;
};
/** /**
* @brief Function template for std::bind. * @brief Function template for std::bind.
* @ingroup binders * @ingroup binders
*/ */
template<typename _Functor, typename... _ArgTypes> template<typename _Functor, typename... _ArgTypes>
inline inline
_Bind<typename _Maybe_wrap_member_pointer<_Functor>::type(_ArgTypes...)> typename _Bind_helper<_Functor, _ArgTypes...>::type
bind(_Functor __f, _ArgTypes... __args) bind(_Functor&& __f, _ArgTypes&&... __args)
{ {
typedef _Maybe_wrap_member_pointer<_Functor> __maybe_type; typedef _Bind_helper<_Functor, _ArgTypes...> __helper_type;
typedef typename __maybe_type::type __functor_type; typedef typename __helper_type::__maybe_type __maybe_type;
typedef _Bind<__functor_type(_ArgTypes...)> __result_type; typedef typename __helper_type::type __result_type;
return __result_type(__maybe_type::__do_wrap(__f), return __result_type(__maybe_type::__do_wrap(std::forward<_Functor>(__f)),
std::forward<_ArgTypes>(__args)...); std::forward<_ArgTypes>(__args)...);
} }
template<typename _Result, typename _Functor, typename... _ArgTypes>
struct _Bindres_helper
{
typedef _Maybe_wrap_member_pointer<typename decay<_Functor>::type>
__maybe_type;
typedef typename __maybe_type::type __functor_type;
typedef _Bind_result<_Result,
__functor_type(typename decay<_ArgTypes>::type...)>
type;
};
/** /**
* @brief Function template for std::bind. * @brief Function template for std::bind<R>.
* @ingroup binders * @ingroup binders
*/ */
template<typename _Result, typename _Functor, typename... _ArgTypes> template<typename _Result, typename _Functor, typename... _ArgTypes>
inline inline
_Bind_result<_Result, typename _Bindres_helper<_Result, _Functor, _ArgTypes...>::type
typename _Maybe_wrap_member_pointer<_Functor>::type bind(_Functor&& __f, _ArgTypes&&... __args)
(_ArgTypes...)>
bind(_Functor __f, _ArgTypes... __args)
{ {
typedef _Maybe_wrap_member_pointer<_Functor> __maybe_type; typedef _Bindres_helper<_Result, _Functor, _ArgTypes...> __helper_type;
typedef typename __maybe_type::type __functor_type; typedef typename __helper_type::__maybe_type __maybe_type;
typedef _Bind_result<_Result, __functor_type(_ArgTypes...)> typedef typename __helper_type::type __result_type;
__result_type; return __result_type(__maybe_type::__do_wrap(std::forward<_Functor>(__f)),
return __result_type(__maybe_type::__do_wrap(__f),
std::forward<_ArgTypes>(__args)...); std::forward<_ArgTypes>(__args)...);
} }
......
...@@ -309,7 +309,7 @@ namespace std ...@@ -309,7 +309,7 @@ namespace std
bool __set = __ignore_failure; bool __set = __ignore_failure;
// all calls to this function are serialized, // all calls to this function are serialized,
// side-effects of invoking __res only happen once // side-effects of invoking __res only happen once
call_once(_M_once, mem_fn(&_State::_M_do_set), this, ref(__res), call_once(_M_once, &_State::_M_do_set, this, ref(__res),
ref(__set)); ref(__set));
if (!__set) if (!__set)
__throw_future_error(int(future_errc::promise_already_satisfied)); __throw_future_error(int(future_errc::promise_already_satisfied));
...@@ -1155,7 +1155,7 @@ namespace std ...@@ -1155,7 +1155,7 @@ namespace std
_M_run(_Args... __args) _M_run(_Args... __args)
{ {
// bound arguments decay so wrap lvalue references // bound arguments decay so wrap lvalue references
auto __bound = std::bind<_Res>(_M_task, auto __bound = std::bind<_Res>(std::ref(_M_task),
_S_maybe_wrap_ref(std::forward<_Args>(__args))...); _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
_Task_setter<_Task_state> __setter{ this, std::move(__bound) }; _Task_setter<_Task_state> __setter{ this, std::move(__bound) };
_M_set_result(std::move(__setter)); _M_set_result(std::move(__setter));
......
...@@ -690,7 +690,7 @@ namespace std ...@@ -690,7 +690,7 @@ namespace std
template<typename _Callable, typename... _Args> template<typename _Callable, typename... _Args>
friend void friend void
call_once(once_flag& __once, _Callable __f, _Args&&... __args); call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
}; };
#ifdef _GLIBCXX_HAVE_TLS #ifdef _GLIBCXX_HAVE_TLS
...@@ -718,15 +718,17 @@ namespace std ...@@ -718,15 +718,17 @@ namespace std
/// call_once /// call_once
template<typename _Callable, typename... _Args> template<typename _Callable, typename... _Args>
void void
call_once(once_flag& __once, _Callable __f, _Args&&... __args) call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
{ {
#ifdef _GLIBCXX_HAVE_TLS #ifdef _GLIBCXX_HAVE_TLS
auto __bound_functor = std::bind<void>(__f, __args...); auto __bound_functor = std::bind<void>(std::forward<_Callable>(__f),
std::forward<_Args>(__args)...);
__once_callable = &__bound_functor; __once_callable = &__bound_functor;
__once_call = &__once_call_impl<decltype(__bound_functor)>; __once_call = &__once_call_impl<decltype(__bound_functor)>;
#else #else
unique_lock<mutex> __functor_lock(__get_once_mutex()); unique_lock<mutex> __functor_lock(__get_once_mutex());
__once_functor = std::bind<void>(__f, __args...); __once_functor = std::bind<void>(std::forward<_Callable>(__f),
std::forward<_Args>(__args)...);
__set_once_functor_lock_ptr(&__functor_lock); __set_once_functor_lock_ptr(&__functor_lock);
#endif #endif
......
...@@ -126,16 +126,14 @@ namespace std ...@@ -126,16 +126,14 @@ namespace std
thread(thread&& __t) thread(thread&& __t)
{ swap(__t); } { swap(__t); }
template<typename _Callable>
explicit thread(_Callable __f)
{
_M_start_thread(_M_make_routine<_Callable>
(std::forward<_Callable>(__f)));
}
template<typename _Callable, typename... _Args> template<typename _Callable, typename... _Args>
explicit
thread(_Callable&& __f, _Args&&... __args) thread(_Callable&& __f, _Args&&... __args)
{ _M_start_thread(_M_make_routine(std::bind(__f, __args...))); } {
_M_start_thread(_M_make_routine(std::bind<void>(
std::forward<_Callable>(__f),
std::forward<_Args>(__args)...)));
}
~thread() ~thread()
{ {
......
...@@ -22,14 +22,24 @@ ...@@ -22,14 +22,24 @@
#include <functional> #include <functional>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
// target must be invoked with cv-quals of call wrapper
struct X struct X
{ {
int operator()() { return 0; } int operator()() { return 0; }
int operator()() const { return 1; } int operator()() const { return 1; }
// int operator()() volatile { return 2; } int operator()() volatile { return 2; }
// int operator()() const volatile { return 3; } int operator()() const volatile { return 3; }
int operator()(int, int, int) { return 0; }
int operator()(int, int, int) const { return 1; }
int operator()(int, int, int) volatile { return 2; }
int operator()(int, int, int) const volatile { return 3; }
}; };
using std::placeholders::_1;
using std::placeholders::_2;
void test01() void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
...@@ -40,15 +50,70 @@ void test01() ...@@ -40,15 +50,70 @@ void test01()
const auto b1 = std::bind(X()); const auto b1 = std::bind(X());
VERIFY( b1() == 1 ); VERIFY( b1() == 1 );
// volatile auto b2 = std::bind(X()); volatile auto b2 = std::bind(X());
// VERIFY( b2() == 2 ); VERIFY( b2() == 2 );
const volatile auto b3 = std::bind(X());
VERIFY( b3() == 3 );
}
void test02()
{
bool test __attribute__((unused)) = true;
auto b0 = std::bind<int>(X());
VERIFY( b0() == 0 );
const auto b1 = std::bind<int>(X());
VERIFY( b1() == 1 );
volatile auto b2 = std::bind<int>(X());
VERIFY( b2() == 2 );
const volatile auto b3 = std::bind<int>(X());
VERIFY( b3() == 3 );
}
void test03()
{
bool test __attribute__((unused)) = true;
auto b0 = std::bind(X(), 0, _1, _2);
VERIFY( b0(0, 0) == 0 );
// const volatile auto b3 = std::bind(X()); const auto b1 = std::bind(X(), _1, 0, _2);
// VERIFY( b3() == 3 ); VERIFY( b1(0, 0) == 1 );
volatile auto b2 = std::bind(X(), _1, _2, 0);
VERIFY( b2(0, 0) == 2 );
const volatile auto b3 = std::bind(X(), _1, 0, _2);
VERIFY( b3(0, 0) == 3 );
} }
void test04()
{
bool test __attribute__((unused)) = true;
auto b0 = std::bind<int>(X(), 0, _1, _2);
VERIFY( b0(0, 0) == 0 );
const auto b1 = std::bind<int>(X(), _1, 0, _2);
VERIFY( b1(0, 0) == 1 );
volatile auto b2 = std::bind<int>(X(), _1, _2, 0);
VERIFY( b2(0, 0) == 2 );
const volatile auto b3 = std::bind<int>(X(), _1, 0, _2);
VERIFY( b3(0, 0) == 3 );
}
int main() int main()
{ {
test01(); test01();
test02();
test03();
test04();
return 0; return 0;
} }
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2010 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 <functional>
#include <testsuite_hooks.h>
// PR libstdc++/45924
struct f
{
f() : i(0) { }
f(f&& r) : i(1) { r.i = -1; }
f(const f&) = delete;
int operator()() { return i; }
int i;
};
void test01()
{
auto b = std::bind(f());
VERIFY( b() == 1 );
auto bc(std::move(b));
VERIFY( bc() == 1 );
VERIFY( b() == -1 );
}
void test02()
{
auto b = std::bind<int>(f());
VERIFY( b() == 1 );
auto bc(std::move(b));
VERIFY( bc() == 1 );
VERIFY( b() == -1 );
}
int main()
{
test01();
test02();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment