[patch] libstdc++/68912 Fix cv-qualifiers in std::bind invocation
Jonathan Wakely
jwakely@redhat.com
Tue Dec 15 17:06:00 GMT 2015
The first patch fixes an inconsistency between the return type and the
function body, as described in the PR.
The second patch removes the TR1 return type support from _Mu, because
it isn't necessary in C++11. The third patch is because the second one
accidentally removed a "volatile" (removing that is fine, because we
never create volatile _Mu, or even a const one, but no point removing
it on only one specialization and leaving it elsewhere).
Tested powerpc64le-linux.
I've committed both to trunk and will apply the first patch (but not
the second and third) to the branches too.
-------------- next part --------------
commit 430066b306ddcd35982a748a34bf3603261f9050
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Dec 15 12:20:01 2015 +0000
Fix cv-qualifiers in std::bind invocation
PR libstdc++/68912
* include/std/functional (_Bind::operator()): Use lvalue functor to
deduce return type.
* testsuite/20_util/bind/68912.cc: New.
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 19caa96..8d39d62 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1034,7 +1034,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
// Call unqualified
template<typename... _Args, typename _Result
- = decltype( std::declval<_Functor>()(
+ = decltype( std::declval<_Functor&>()(
_Mu<_Bound_args>()( std::declval<_Bound_args&>(),
std::declval<tuple<_Args...>&>() )... ) )>
_Result
@@ -1048,7 +1048,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
// Call as const
template<typename... _Args, typename _Result
= decltype( std::declval<typename enable_if<(sizeof...(_Args) >= 0),
- typename add_const<_Functor>::type>::type>()(
+ typename add_const<_Functor>::type&>::type>()(
_Mu<_Bound_args>()( std::declval<const _Bound_args&>(),
std::declval<tuple<_Args...>&>() )... ) )>
_Result
@@ -1062,7 +1062,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
// Call as volatile
template<typename... _Args, typename _Result
= decltype( std::declval<typename enable_if<(sizeof...(_Args) >= 0),
- typename add_volatile<_Functor>::type>::type>()(
+ typename add_volatile<_Functor>::type&>::type>()(
_Mu<_Bound_args>()( std::declval<volatile _Bound_args&>(),
std::declval<tuple<_Args...>&>() )... ) )>
_Result
@@ -1076,7 +1076,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
// Call as const volatile
template<typename... _Args, typename _Result
= decltype( std::declval<typename enable_if<(sizeof...(_Args) >= 0),
- typename add_cv<_Functor>::type>::type>()(
+ typename add_cv<_Functor>::type&>::type>()(
_Mu<_Bound_args>()( std::declval<const volatile _Bound_args&>(),
std::declval<tuple<_Args...>&>() )... ) )>
_Result
diff --git a/libstdc++-v3/testsuite/20_util/bind/68912.cc b/libstdc++-v3/testsuite/20_util/bind/68912.cc
new file mode 100644
index 0000000..7a00b75
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/68912.cc
@@ -0,0 +1,53 @@
+// Copyright (C) 2015 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include<functional>
+
+struct Wrong {};
+struct A {};
+struct B {};
+struct C{};
+struct D{};
+
+struct X {
+ A operator()(int, double) & { return {}; }
+ Wrong operator()(int, double) && {return {}; }
+
+ B operator()(int, double) const & { return {}; }
+ Wrong operator()(int, double) const && {return {}; }
+
+ C operator()(int, double) volatile & { return {}; }
+ Wrong operator()(int, double) volatile && {return {}; }
+
+ D operator()(int, double) const volatile & { return {}; }
+ Wrong operator()(int, double) const volatile && {return {}; }
+};
+
+void test01()
+{
+ auto bound = std::bind(X{}, 5, std::placeholders::_1);
+ A res = bound(1.0);
+ const auto bound_c = bound;
+ B res_c = bound_c(1.0);
+ volatile auto bound_v = bound;
+ C res_v = bound_v(1.0);
+ volatile const auto bound_cv = bound;
+ D res_cv = bound_cv(1.0);
+}
-------------- next part --------------
commit 44698303952f8e1215756adf53f72ca72cf0c59d
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Dec 15 13:16:58 2015 +0000
Remove vestigial traces of std::tr1::bind
* include/std/functional (is_placeholder, is_bind_expression): Update
comments.
(_Safe_tuple_element): Replace with _Safe_tuple_element_t alias
template.
(_Mu): Remove vestigial TR1 return types and update coments.
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 8d39d62..99af29e 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -654,9 +654,11 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
}
/**
- * @brief Determines if the given type _Tp is a function object
+ * @brief Determines if the given type _Tp is a function object that
* should be treated as a subexpression when evaluating calls to
- * function objects returned by bind(). [TR1 3.6.1]
+ * function objects returned by bind().
+ *
+ * C++11 [func.bind.isbind].
* @ingroup binders
*/
template<typename _Tp>
@@ -665,7 +667,9 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
/**
* @brief Determines if the given type _Tp is a placeholder in a
- * bind() expression and, if so, which placeholder it is. [TR1 3.6.2]
+ * bind() expression and, if so, which placeholder it is.
+ *
+ * C++11 [func.bind.isplace].
* @ingroup binders
*/
template<typename _Tp>
@@ -740,45 +744,16 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
: public integral_constant<int, _Num>
{ };
- /**
- * Used by _Safe_tuple_element to indicate that there is no tuple
- * element at this position.
- */
- struct _No_tuple_element;
- /**
- * Implementation helper for _Safe_tuple_element. This primary
- * template handles the case where it is safe to use @c
- * tuple_element.
- */
- template<std::size_t __i, typename _Tuple, bool _IsSafe>
- struct _Safe_tuple_element_impl
- : tuple_element<__i, _Tuple> { };
-
- /**
- * Implementation helper for _Safe_tuple_element. This partial
- * specialization handles the case where it is not safe to use @c
- * tuple_element. We just return @c _No_tuple_element.
- */
- template<std::size_t __i, typename _Tuple>
- struct _Safe_tuple_element_impl<__i, _Tuple, false>
- {
- typedef _No_tuple_element type;
- };
-
- /**
- * Like tuple_element, but returns @c _No_tuple_element when
- * tuple_element would return an error.
- */
+ // Like tuple_element_t but SFINAE-friendly.
template<std::size_t __i, typename _Tuple>
- struct _Safe_tuple_element
- : _Safe_tuple_element_impl<__i, _Tuple,
- (__i < tuple_size<_Tuple>::value)>
- { };
+ using _Safe_tuple_element_t
+ = typename enable_if<(__i < tuple_size<_Tuple>::value),
+ tuple_element<__i, _Tuple>>::type::type;
/**
* Maps an argument to bind() into an actual argument to the bound
- * function object [TR1 3.6.3/5]. Only the first parameter should
+ * function object [func.bind.bind]/10. Only the first parameter should
* be specified: the rest are used to determine among the various
* implementations. Note that, although this class is a function
* object, it isn't entirely normal because it takes only two
@@ -794,20 +769,19 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
/**
* If the argument is reference_wrapper<_Tp>, returns the
- * underlying reference. [TR1 3.6.3/5 bullet 1]
+ * underlying reference.
+ * C++11 [func.bind.bind] p10 bullet 1.
*/
template<typename _Tp>
class _Mu<reference_wrapper<_Tp>, false, false>
{
public:
- typedef _Tp& result_type;
-
/* Note: This won't actually work for const volatile
* reference_wrappers, because reference_wrapper::get() is const
* but not volatile-qualified. This might be a defect in the TR.
*/
template<typename _CVRef, typename _Tuple>
- result_type
+ _Tp&
operator()(_CVRef& __arg, _Tuple&) const volatile
{ return __arg.get(); }
};
@@ -815,7 +789,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
/**
* If the argument is a bind expression, we invoke the underlying
* function object with the same cv-qualifiers as we are given and
- * pass along all of our arguments (unwrapped). [TR1 3.6.3/5 bullet 2]
+ * pass along all of our arguments (unwrapped).
+ * C++11 [func.bind.bind] p10 bullet 2.
*/
template<typename _Arg>
class _Mu<_Arg, true, false>
@@ -849,58 +824,35 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
/**
* If the argument is a placeholder for the Nth argument, returns
* a reference to the Nth argument to the bind function object.
- * [TR1 3.6.3/5 bullet 3]
+ * C++11 [func.bind.bind] p10 bullet 3.
*/
template<typename _Arg>
class _Mu<_Arg, false, true>
{
public:
- template<typename _Signature> class result;
-
- template<typename _CVMu, typename _CVArg, typename _Tuple>
- class result<_CVMu(_CVArg, _Tuple)>
- {
- // Add a reference, if it hasn't already been done for us.
- // This allows us to be a little bit sloppy in constructing
- // the tuple that we pass to result_of<...>.
- typedef typename _Safe_tuple_element<(is_placeholder<_Arg>::value
- - 1), _Tuple>::type
- __base_type;
-
- public:
- typedef typename add_rvalue_reference<__base_type>::type type;
- };
-
template<typename _Tuple>
- typename result<_Mu(_Arg, _Tuple)>::type
+ _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&&
operator()(const volatile _Arg&, _Tuple& __tuple) const volatile
{
- return std::forward<typename result<_Mu(_Arg, _Tuple)>::type>(
+ using __type
+ = __tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>;
+ return std::forward<__type>(
::std::get<(is_placeholder<_Arg>::value - 1)>(__tuple));
}
};
/**
* If the argument is just a value, returns a reference to that
- * value. The cv-qualifiers on the reference are the same as the
- * cv-qualifiers on the _Mu object. [TR1 3.6.3/5 bullet 4]
+ * value. The cv-qualifiers on the reference are determined by the caller.
+ * C++11 [func.bind.bind] p10 bullet 4.
*/
template<typename _Arg>
class _Mu<_Arg, false, false>
{
public:
- template<typename _Signature> struct result;
-
- template<typename _CVMu, typename _CVArg, typename _Tuple>
- struct result<_CVMu(_CVArg, _Tuple)>
- {
- typedef typename add_lvalue_reference<_CVArg>::type type;
- };
-
- // Pick up the cv-qualifiers of the argument
template<typename _CVArg, typename _Tuple>
_CVArg&&
- operator()(_CVArg&& __arg, _Tuple&) const volatile
+ operator()(_CVArg&& __arg, _Tuple&) const
{ return std::forward<_CVArg>(__arg); }
};
-------------- next part --------------
commit 59f967f86f9b06373e6a5b4e3703df234e61dd08
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Dec 15 14:23:43 2015 +0000
Restore accidentally-removed volatile qualifier
* include/std/functional (_Mu<_Arg, false, false>::operator()): Restore
accidentally-removed volatile qualifier.
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 99af29e..ff29a57 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -852,7 +852,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
public:
template<typename _CVArg, typename _Tuple>
_CVArg&&
- operator()(_CVArg&& __arg, _Tuple&) const
+ operator()(_CVArg&& __arg, _Tuple&) const volatile
{ return std::forward<_CVArg>(__arg); }
};
More information about the Libstdc++
mailing list