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
This commit is contained in:
Jonathan Wakely 2009-12-24 14:54:33 +00:00 committed by Jonathan Wakely
parent 0800b8ea79
commit c5a2375241
3 changed files with 128 additions and 14 deletions

View File

@ -1,3 +1,9 @@
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>
* include/bits/stl_deque.h (copy_backward(_Deque_iterator,

View File

@ -1130,6 +1130,16 @@ namespace std
{ 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().
template<typename _Signature>
struct _Bind;
@ -1262,44 +1272,93 @@ namespace std
_Functor _M_f;
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
template<typename... _Args, int... _Indexes>
template<typename _Res, typename... _Args, int... _Indexes>
_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>()
(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
template<typename... _Args, int... _Indexes>
template<typename _Res, typename... _Args, int... _Indexes>
_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>()
(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
template<typename... _Args, int... _Indexes>
template<typename _Res, typename... _Args, int... _Indexes>
_Result
__call(const tuple<_Args...>& __args,
_Index_tuple<_Indexes...>) volatile
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
typename __disable_if_void<_Res>::type = 0) volatile
{
return _M_f(_Mu<_Bound_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
template<typename... _Args, int... _Indexes>
template<typename _Res, typename... _Args, int... _Indexes>
_Result
__call(const tuple<_Args...>& __args,
_Index_tuple<_Indexes...>) const volatile
__call(const tuple<_Args...>& __args, _Index_tuple<_Indexes...>,
typename __disable_if_void<_Res>::type = 0) const volatile
{
return _M_f(_Mu<_Bound_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:
typedef _Result result_type;
@ -1312,7 +1371,7 @@ namespace std
result_type
operator()(_Args&... __args)
{
return this->__call(tie(__args...), _Bound_indexes());
return this->__call<_Result>(tie(__args...), _Bound_indexes());
}
// Call as const
@ -1320,7 +1379,7 @@ namespace std
result_type
operator()(_Args&... __args) const
{
return this->__call(tie(__args...), _Bound_indexes());
return this->__call<_Result>(tie(__args...), _Bound_indexes());
}
// Call as volatile
@ -1328,7 +1387,7 @@ namespace std
result_type
operator()(_Args&... __args) volatile
{
return this->__call(tie(__args...), _Bound_indexes());
return this->__call<_Result>(tie(__args...), _Bound_indexes());
}
// Call as const volatile
@ -1336,7 +1395,7 @@ namespace std
result_type
operator()(_Args&... __args) const volatile
{
return this->__call(tie(__args...), _Bound_indexes());
return this->__call<_Result>(tie(__args...), _Bound_indexes());
}
};

View File

@ -0,0 +1,49 @@
// { 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;
}