diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 46412780c96..f19aabc7e26 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2014-11-11 Jonathan Wakely + + * include/std/functional (_Mem_fn_traits): Add partial specializations + for varargs functions. + (_Mem_fn_base): Do not check arguments are convertible for varargs. + (_Bind_check_arity): Add partial specializations for varargs functions. + * include/std/type_traits (__bool_constant): Add alias template. + * testsuite/20_util/bind/ref_neg.cc: Adjust dg-error. + * testsuite/20_util/bind/refqual.cc: New, test ref-qualifiers. + * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error. + * testsuite/20_util/function_objects/mem_fn/refqual.cc: Test varargs. + * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust + dg-error. + * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Adjust + dg-error. + 2014-11-11 Siva Chandra Reddy * testsuite/libstdc++-xmethods/associative-containers.cc: Add new diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 25ec1b351b8..92489b7d4b9 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -512,113 +512,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) using __arity = integral_constant; }; - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...)> - : _Mem_fn_traits_base<_Res, _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...); - using __lvalue = true_type; - using __rvalue = true_type; +#define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __pmf_type = _Res (_Class::*)(_ArgTypes...) _CV _REF; \ + using __lvalue = _LVAL; \ + using __rvalue = _RVAL; \ + using __vararg = false_type; \ + }; \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __pmf_type = _Res (_Class::*)(_ArgTypes... ...) _CV _REF; \ + using __lvalue = _LVAL; \ + using __rvalue = _RVAL; \ + using __vararg = true_type; \ }; - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const> - : _Mem_fn_traits_base<_Res, const _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) const; - using __lvalue = true_type; - using __rvalue = true_type; - }; +#define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL) - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) volatile> - : _Mem_fn_traits_base<_Res, volatile _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) volatile; - using __lvalue = true_type; - using __rvalue = true_type; - }; +_GLIBCXX_MEM_FN_TRAITS( , true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const volatile> - : _Mem_fn_traits_base<_Res, const volatile _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) const volatile; - using __lvalue = true_type; - using __rvalue = true_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...)&> - : _Mem_fn_traits_base<_Res, _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...)&; - using __lvalue = true_type; - using __rvalue = false_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const&> - : _Mem_fn_traits_base<_Res, const _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) const&; - using __lvalue = true_type; - using __rvalue = false_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) volatile&> - : _Mem_fn_traits_base<_Res, volatile _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) volatile&; - using __lvalue = true_type; - using __rvalue = false_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const volatile&> - : _Mem_fn_traits_base<_Res, const volatile _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) const volatile&; - using __lvalue = true_type; - using __rvalue = false_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...)&&> - : _Mem_fn_traits_base<_Res, _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...)&&; - using __lvalue = false_type; - using __rvalue = true_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const&&> - : _Mem_fn_traits_base<_Res, const _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) const&&; - using __lvalue = false_type; - using __rvalue = true_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) volatile&&> - : _Mem_fn_traits_base<_Res, volatile _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) volatile&&; - using __lvalue = false_type; - using __rvalue = true_type; - }; - - template - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const volatile&&> - : _Mem_fn_traits_base<_Res, const volatile _Class, _ArgTypes...> - { - using __pmf_type = _Res (_Class::*)(_ArgTypes...) const volatile&&; - using __lvalue = false_type; - using __rvalue = true_type; - }; +#undef _GLIBCXX_MEM_FN_TRAITS +#undef _GLIBCXX_MEM_FN_TRAITS2 template::value> @@ -627,15 +552,74 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { using _Traits = _Mem_fn_traits<_MemFunPtr>; - public: - using result_type = typename _Traits::__result_type; - using _Arity = typename _Traits::__arity; - - private: using _Class = typename _Traits::__class_type; using _ArgTypes = typename _Traits::__arg_types; using _Pmf = typename _Traits::__pmf_type; + using _Arity = typename _Traits::__arity; + using _Varargs = typename _Traits::__vararg; + + template + friend struct _Bind_check_arity; + + // for varargs functions we just check the number of arguments, + // otherwise we also check they are convertible. + template + using _CheckArgs = typename conditional<_Varargs::value, + __bool_constant<(_Args::value >= _ArgTypes::value)>, + _AllConvertible<_Args, _ArgTypes> + >::type; + + public: + using result_type = typename _Traits::__result_type; + + explicit _Mem_fn_base(_Pmf __pmf) : _M_pmf(__pmf) { } + + // Handle objects + template>>> + result_type + operator()(_Class& __object, _Args&&... __args) const + { return (__object.*_M_pmf)(std::forward<_Args>(__args)...); } + + template>>> + result_type + operator()(_Class&& __object, _Args&&... __args) const + { + return (std::move(__object).*_M_pmf)(std::forward<_Args>(__args)...); + } + + // Handle pointers + template>>> + result_type + operator()(_Class* __object, _Args&&... __args) const + { return (__object->*_M_pmf)(std::forward<_Args>(__args)...); } + + // Handle smart pointers, references and pointers to derived + template, _NotSame<_Class*, _Tp>, + _CheckArgs<_Pack<_Args...>>>> + result_type + operator()(_Tp&& __object, _Args&&... __args) const + { + return _M_call(std::forward<_Tp>(__object), &__object, + std::forward<_Args>(__args)...); + } + + // Handle reference wrappers + template, typename _Traits::__lvalue, + _CheckArgs<_Pack<_Args...>>>> + result_type + operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const + { return operator()(__ref.get(), std::forward<_Args>(__args)...); } + + private: template result_type _M_call(_Tp&& __object, const volatile _Class *, @@ -650,75 +634,6 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) _M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const { return ((*__ptr).*_M_pmf)(std::forward<_Args>(__args)...); } - // Require each _Args to be convertible to corresponding _ArgTypes - template - using _RequireValidArgs - = _Require<_AllConvertible<_Pack<_Args...>, _ArgTypes>>; - - // Require each _Args to be convertible to corresponding _ArgTypes - // and require _Tp is not _Class, _Class& or _Class* - template - using _RequireValidArgs2 - = _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>, - _AllConvertible<_Pack<_Args...>, _ArgTypes>>; - - // Require each _Args to be convertible to corresponding _ArgTypes - // and require _Tp is _Class or derived from _Class - template - using _RequireValidArgs3 - = _Require, - _AllConvertible<_Pack<_Args...>, _ArgTypes>>; - - public: - explicit _Mem_fn_base(_Pmf __pmf) : _M_pmf(__pmf) { } - - // Handle objects - template, _ArgTypes>>> - result_type - operator()(_Class& __object, _Args&&... __args) const - { return (__object.*_M_pmf)(std::forward<_Args>(__args)...); } - - template, _ArgTypes>>> - result_type - operator()(_Class&& __object, _Args&&... __args) const - { - return (std::move(__object).*_M_pmf)(std::forward<_Args>(__args)...); - } - - // Handle pointers - template, _ArgTypes>>> - result_type - operator()(_Class* __object, _Args&&... __args) const - { return (__object->*_M_pmf)(std::forward<_Args>(__args)...); } - - // Handle smart pointers, references and pointers to derived - // TODO how to constrain to lvalue/rvalue here? constrain _M_call? - template, _NotSame<_Class*, _Tp>, - _AllConvertible<_Pack<_Args...>, _ArgTypes>>> - result_type - operator()(_Tp&& __object, _Args&&... __args) const - { - return _M_call(std::forward<_Tp>(__object), &__object, - std::forward<_Args>(__args)...); - } - - // Handle reference wrappers - template, - typename _Traits::__lvalue, - _AllConvertible<_Pack<_Args...>, _ArgTypes>>> - result_type - operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const - { return operator()(__ref.get(), std::forward<_Args>(__args)...); } - - private: _Pmf _M_pmf; }; @@ -750,9 +665,13 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) -> decltype((*__ptr).*std::declval<__pm_type&>()) { return (*__ptr).*_M_pm; } - public: using _Arity = integral_constant; + using _Varargs = false_type; + template + friend struct _Bind_check_arity; + + public: explicit _Mem_fn_base(_Res _Class::*__pm) noexcept : _M_pm(__pm) { } @@ -1493,12 +1412,22 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) "Wrong number of arguments for function"); }; + template + struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args), + "Wrong number of arguments for function"); + }; + template struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...> { using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity; - static_assert(sizeof...(_BoundArgs) == _Arity::value + 1, - "Wrong number of arguments for pointer-to-member"); + using _Varargs = typename _Mem_fn<_Tp _Class::*>::_Varargs; + static_assert(_Varargs::value + ? sizeof...(_BoundArgs) >= _Arity::value + 1 + : sizeof...(_BoundArgs) == _Arity::value + 1, + "Wrong number of arguments for pointer-to-member"); }; // Trait type used to remove std::bind() from overload set via SFINAE diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index b92bbf09287..cecc7dc2697 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -89,6 +89,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// The type used as a compile-time boolean with false value. typedef integral_constant false_type; + template + using __bool_constant = integral_constant; + // Meta programming helper types. template diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc index 4e627cfaf48..7810968663d 100644 --- a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc +++ b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc @@ -30,10 +30,10 @@ void test01() { const int dummy = 0; std::bind(&inc, _1)(0); // { dg-error "no match" } - // { dg-error "rvalue|const" "" { target *-*-* } 1207 } - // { dg-error "rvalue|const" "" { target *-*-* } 1221 } - // { dg-error "rvalue|const" "" { target *-*-* } 1235 } - // { dg-error "rvalue|const" "" { target *-*-* } 1249 } + // { dg-error "rvalue|const" "" { target *-*-* } 1126 } + // { dg-error "rvalue|const" "" { target *-*-* } 1140 } + // { dg-error "rvalue|const" "" { target *-*-* } 1154 } + // { dg-error "rvalue|const" "" { target *-*-* } 1168 } std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" } } diff --git a/libstdc++-v3/testsuite/20_util/bind/refqual.cc b/libstdc++-v3/testsuite/20_util/bind/refqual.cc new file mode 100644 index 00000000000..76f4f5c4093 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bind/refqual.cc @@ -0,0 +1,43 @@ +// Copyright (C) 2014 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include + +struct X +{ + int f() const& { return 0; } + int g(int i, ...)& { return i; } +}; + +void +test01() +{ + X x; + auto b = std::bind(&X::f, &x); + VERIFY( b() == 0 ); + auto bb = std::bind(&X::g, &x, 1, 2); + VERIFY( bb() == 1 ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc index debcb28fd35..cdcbdbe87f7 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // . -// { dg-error "static assertion failed" "" { target *-*-* } 2201 } +// { dg-error "static assertion failed" "" { target *-*-* } 2204 } #include diff --git a/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc b/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc index 35a66e55410..4f3a64bacfa 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc @@ -24,6 +24,7 @@ struct Foo { void r()&& { } int l() const& { return 0; } + void lv(int, ...)& { } }; void test01() @@ -31,4 +32,5 @@ void test01() Foo f; int i = std::mem_fn(&Foo::l)( f ); std::mem_fn(&Foo::r)( std::move(f) ); + std::mem_fn(&Foo::lv)( f, 1, 2, 3 ); } diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc index aeef380ee93..b38ffdf87d8 100644 --- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1866 } -// { dg-error "declaration of" "" { target *-*-* } 1830 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1869 } +// { dg-error "declaration of" "" { target *-*-* } 1833 } diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc index ebfdc429444..d2e11a698a9 100644 --- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1754 } -// { dg-error "declaration of" "" { target *-*-* } 1718 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1757 } +// { dg-error "declaration of" "" { target *-*-* } 1721 }