Commit c5a23752 by Jonathan Wakely Committed by Jonathan Wakely

functional (bind): Avoid invalid instantiations for bind<void>.

2009-12-24  Jonathan Wakely  <jwakely.gcc@gmail.com>

	* include/std/functional (bind): Avoid invalid instantiations
	for bind<void>.
	* testsuite/20_util/bind/conv_result.cc: New.

From-SVN: r155457
parent 0800b8ea
2009-12-24 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/std/functional (bind): Avoid invalid instantiations
for bind<void>.
* testsuite/20_util/bind/conv_result.cc: New.
2009-12-24 Paolo Carlini <paolo.carlini@oracle.com> 2009-12-24 Paolo Carlini <paolo.carlini@oracle.com>
* include/bits/stl_deque.h (copy_backward(_Deque_iterator, * include/bits/stl_deque.h (copy_backward(_Deque_iterator,
......
...@@ -1130,6 +1130,16 @@ namespace std ...@@ -1130,6 +1130,16 @@ namespace std
{ return type(__pm); } { return type(__pm); }
}; };
// Specialization needed to prevent "forming reference to void" errors when
// bind<void>() is called, because argument deduction instantiates
// _Maybe_wrap_member_pointer<void> outside the immediate context where
// SFINAE applies.
template<>
struct _Maybe_wrap_member_pointer<void>
{
typedef void type;
};
/// 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;
...@@ -1262,44 +1272,93 @@ namespace std ...@@ -1262,44 +1272,93 @@ namespace std
_Functor _M_f; _Functor _M_f;
tuple<_Bound_args...> _M_bound_args; tuple<_Bound_args...> _M_bound_args;
// sfinae types
template<typename _Res>
struct __enable_if_void : enable_if<is_void<_Res>::value, int> { };
template<typename _Res>
struct __disable_if_void : enable_if<!is_void<_Res>::value, int> { };
// Call unqualified // Call unqualified
template<typename... _Args, int... _Indexes> template<typename _Res, typename... _Args, int... _Indexes>
_Result _Result
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>) __call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
typename __disable_if_void<_Res>::type = 0)
{ {
return _M_f(_Mu<_Bound_args>() return _M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), __args)...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call unqualified, return void
template<typename _Res, typename... _Args, int... _Indexes>
void
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
typename __enable_if_void<_Res>::type = 0)
{
_M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), __args)...);
}
// Call as const // Call as const
template<typename... _Args, int... _Indexes> template<typename _Res, typename... _Args, int... _Indexes>
_Result _Result
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>) const __call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
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), __args)...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const, return void
template<typename _Res, typename... _Args, int... _Indexes>
void
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
typename __enable_if_void<_Res>::type = 0) const
{
_M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), __args)...);
}
// Call as volatile // Call as volatile
template<typename... _Args, int... _Indexes> template<typename _Res, typename... _Args, int... _Indexes>
_Result _Result
__call(const tuple<_Args...>& __args, __call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
_Index_tuple<_Indexes...>) 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), __args)...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as volatile, return void
template<typename _Res, typename... _Args, int... _Indexes>
void
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
typename __enable_if_void<_Res>::type = 0) volatile
{
_M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), __args)...);
}
// Call as const volatile // Call as const volatile
template<typename... _Args, int... _Indexes> template<typename _Res, typename... _Args, int... _Indexes>
_Result _Result
__call(const tuple<_Args...>& __args, __call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
_Index_tuple<_Indexes...>) 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), __args)...); (get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const volatile, return void
template<typename _Res, typename... _Args, int... _Indexes>
void
__call(const tuple<_Args...>& __args,
_Index_tuple<_Indexes...>,
typename __enable_if_void<_Res>::type = 0) const volatile
{
_M_f(_Mu<_Bound_args>()
(get<_Indexes>(_M_bound_args), __args)...);
}
public: public:
typedef _Result result_type; typedef _Result result_type;
...@@ -1312,7 +1371,7 @@ namespace std ...@@ -1312,7 +1371,7 @@ namespace std
result_type result_type
operator()(_Args&... __args) operator()(_Args&... __args)
{ {
return this->__call(tie(__args...), _Bound_indexes()); return this->__call<_Result>(tie(__args...), _Bound_indexes());
} }
// Call as const // Call as const
...@@ -1320,7 +1379,7 @@ namespace std ...@@ -1320,7 +1379,7 @@ namespace std
result_type result_type
operator()(_Args&... __args) const operator()(_Args&... __args) const
{ {
return this->__call(tie(__args...), _Bound_indexes()); return this->__call<_Result>(tie(__args...), _Bound_indexes());
} }
// Call as volatile // Call as volatile
...@@ -1328,7 +1387,7 @@ namespace std ...@@ -1328,7 +1387,7 @@ namespace std
result_type result_type
operator()(_Args&... __args) volatile operator()(_Args&... __args) volatile
{ {
return this->__call(tie(__args...), _Bound_indexes()); return this->__call<_Result>(tie(__args...), _Bound_indexes());
} }
// Call as const volatile // Call as const volatile
...@@ -1336,7 +1395,7 @@ namespace std ...@@ -1336,7 +1395,7 @@ namespace std
result_type result_type
operator()(_Args&... __args) const volatile operator()(_Args&... __args) const volatile
{ {
return this->__call(tie(__args...), _Bound_indexes()); return this->__call<_Result>(tie(__args...), _Bound_indexes());
} }
}; };
......
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2009 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/>.
// 20.7.11 Function template bind
#include <functional>
#include <testsuite_hooks.h>
struct X
{
typedef int result_type;
int operator()(int i) const { return i+1; }
bool b;
};
void test01()
{
bool test __attribute__((unused)) = true;
using std::bind;
using std::ref;
::X x = { true };
// test bind<R> form
bind<void>(ref(x), 1)();
VERIFY( bind<long>(ref(x), 1)() == 2 );
bind<void>(&::X::b, ref(x))();
VERIFY( bind<int>(&::X::b, ref(x))() == 1 );
}
int main()
{
test01();
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