diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4ca96b2878aa..ad2d892c83ab 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2009-12-24 Jonathan Wakely + + * include/std/functional (bind): Avoid invalid instantiations + for bind. + * testsuite/20_util/bind/conv_result.cc: New. + 2009-12-24 Paolo Carlini * include/bits/stl_deque.h (copy_backward(_Deque_iterator, diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 19503bdf05e0..3be8ed76c3ec 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() is called, because argument deduction instantiates + // _Maybe_wrap_member_pointer outside the immediate context where + // SFINAE applies. + template<> + struct _Maybe_wrap_member_pointer + { + typedef void type; + }; + /// Type of the function object returned from bind(). template struct _Bind; @@ -1262,44 +1272,93 @@ namespace std _Functor _M_f; tuple<_Bound_args...> _M_bound_args; + // sfinae types + template + struct __enable_if_void : enable_if::value, int> { }; + template + struct __disable_if_void : enable_if::value, int> { }; + // Call unqualified - template + template _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 + 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 + template _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 + 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 + template _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 + 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 + template _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 + 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 000000000000..440a5276bdfc --- /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 +// . + +// 20.7.11 Function template bind + +#include +#include + +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 form + bind(ref(x), 1)(); + VERIFY( bind(ref(x), 1)() == 2 ); + bind(&::X::b, ref(x))(); + VERIFY( bind(&::X::b, ref(x))() == 1 ); +} + +int main() +{ + test01(); + return 0; +}