mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-13 13:54:05 +08:00
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:
parent
0800b8ea79
commit
c5a2375241
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
49
libstdc++-v3/testsuite/20_util/bind/conv_result.cc
Normal file
49
libstdc++-v3/testsuite/20_util/bind/conv_result.cc
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user