Fix cv-qualifiers in std::bind invocation
authorJonathan Wakely <jwakely@redhat.com>
Tue, 15 Dec 2015 14:17:17 +0000 (14:17 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 15 Dec 2015 14:17:17 +0000 (14:17 +0000)
PR libstdc++/68912
* include/std/functional (_Bind::operator()): Use lvalue functor to
deduce return type.
* testsuite/20_util/bind/68912.cc: New.

From-SVN: r231652

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/functional
libstdc++-v3/testsuite/20_util/bind/68912.cc [new file with mode: 0644]

index 7f4e79787fad26f5594a3a5f1e3deee805280746..295dcf17c335e77453add6c4666b53edd244fad1 100644 (file)
@@ -1,3 +1,10 @@
+2015-12-15  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/68912
+       * include/std/functional (_Bind::operator()): Use lvalue functor to
+       deduce return type.
+       * testsuite/20_util/bind/68912.cc: New.
+
 2015-12-15  Tim Shen  <timshen@google.com>
 
        PR libstdc++/68863
index 19caa96b08aba369a035885f339f1a9bcdb4ecae..8d39d622b4b730c31b4e80d6b599b9d0b8fcc8c8 100644 (file)
@@ -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 (file)
index 0000000..7a00b75
--- /dev/null
@@ -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);
+}