[c++0x patch] allow std::bind<void>
Jonathan Wakely
jwakely.gcc@gmail.com
Thu Dec 24 14:18:00 GMT 2009
This patch fixes the included testcase, which failed in two ways.
Firstly, overload resolution for bind<void>(...) tries to match the
first overload of bind, causing an invalid instantiation in a context
where SFINAE doesn't apply, producing:
error: forming reference to void
Fixed by adding a valid specialisation so that overload resolution can proceed.
Secondly, if the bound function returns non-void we instantiate something like:
template <typename>
struct Bind_result {
template<typename... Args>
void
operator()(Args... a)
{ return _M_fn(a); } // error
};
which produces:
error: return-statement with a value, in function returning 'void'
Fixed by overloading the call functions and using SFINAE on
is_void<Res> to enable/disable overloads.
* include/std/functional (bind): Avoid invalid instantiations
for bind<void>.
* testsuite/20_util/bind/conv_result.cc: New.
Tested x86_64/Linux. I plan to commit this later today.
-------------- next part --------------
Index: include/std/functional
===================================================================
--- include/std/functional (revision 155456)
+++ include/std/functional (working copy)
@@ -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());
}
};
Index: testsuite/20_util/bind/conv_result.cc
===================================================================
--- testsuite/20_util/bind/conv_result.cc (revision 0)
+++ testsuite/20_util/bind/conv_result.cc (revision 0)
@@ -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;
+}
More information about the Libstdc++
mailing list