aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely.gcc@gmail.com>2009-12-24 14:54:33 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2009-12-24 14:54:33 +0000
commitc5a2375241372f3c2106878a91843c3285fb72be (patch)
tree464a2b027085edd5b47708d7e6fa1be0ccf6c819 /libstdc++-v3
parent0800b8ea794cfb5e7066a3b5128efb40b98a0ff6 (diff)
downloadgcc-c5a2375241372f3c2106878a91843c3285fb72be.zip
gcc-c5a2375241372f3c2106878a91843c3285fb72be.tar.gz
gcc-c5a2375241372f3c2106878a91843c3285fb72be.tar.bz2
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
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog6
-rw-r--r--libstdc++-v3/include/std/functional87
-rw-r--r--libstdc++-v3/testsuite/20_util/bind/conv_result.cc49
3 files changed, 128 insertions, 14 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 4ca96b2..ad2d892 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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,
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 19503bdf..3be8ed7 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -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());
}
};
diff --git a/libstdc++-v3/testsuite/20_util/bind/conv_result.cc b/libstdc++-v3/testsuite/20_util/bind/conv_result.cc
new file mode 100644
index 0000000..440a527
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/conv_result.cc
@@ -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;
+}