From patchwork Tue Nov 11 23:58:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 409715 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C340714012C for ; Wed, 12 Nov 2014 10:58:22 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=CsSCSPDGI6/DmyWnCrA76wFWekgx5Qhpxbj21bXcgtatUMPw+yNIY WFx2sqCKfuO8aF+jG2E25XRnuY0Ou3pZMtNf42YcxY8YE3l1FuG6gH8FRoPTB7RO uKltNPFfLlEhGurJBN/qH+WhFAi1mAZcg1DP49OsG42DFcqqQEnt2c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=yK6ux+p6CO/VrIgscbNK1suWN2o=; b=SuZXMiXoAxWAem3qD6cZ OvJubEj55ns6nm8TU/N8dkYGlivdD5EhIKIgjvCahpScku5rlIVWumir+EtzEJ0a rLn/GUTv7n8r+4Uvv9YK6U27O9m5lv3FISizJ5Hkvm5/jXpUHXAzlw6a+XKE4DQg YeiLgPB5yZxEN+EyK/2hDTQ= Received: (qmail 1730 invoked by alias); 11 Nov 2014 23:58:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 1712 invoked by uid 89); 11 Nov 2014 23:58:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 11 Nov 2014 23:58:07 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sABNw6ZS006717 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Nov 2014 18:58:06 -0500 Received: from localhost (ovpn-116-136.ams2.redhat.com [10.36.116.136]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sABNw5pa017403; Tue, 11 Nov 2014 18:58:05 -0500 Date: Tue, 11 Nov 2014 23:58:04 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [patch] LWG 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14 Message-ID: <20141111235804.GP5191@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) This implements LWG 2048. We've been shipping a SFINAE-friendly iterator_traits in C++11 mode for years, but this adjusts it to match the form that will be in the next standard i.e. require all the nested members, not only iterator_category. To implement this I added __void_t, which is identical to the std::void_t that's going into C++17 based on N3911, but we can use it in C++11 mode. I've run a few tests and using __void_t in our _GLIBCXX_HAS_NESTED_TYPE macro reduces the front-end's memory footprint and compile-time compared to the old implementation, so I've altered that. I've also changed a couple of places to use void_t directly instead of using the _GLIBCXX_HAS_NESTED_TYPE macro at all. Tested x86_64-linux, committed to trunk. commit 57477dc54a9b74a3aaa8d50949d8aa7b23488a4c Author: Jonathan Wakely Date: Tue Nov 11 18:55:33 2014 +0000 Define __void_t and SFINAE-friendly iterator_traits. * include/std/type_traits (__void_t): Define new alias template. (_GLIBCXX_HAS_NESTED_TYPE): Redefine using __void_t. * include/std/functional (_Maybe_get_result_type): Likewise. * include/bits/stl_iterator_base_types.h (__iterator_traits): Likewise. * include/bits/uses_allocator.h (__uses_allocator_helper): Likewise. * testsuite/20_util/bind/ref_neg.cc: Adjust dg-error. * testsuite/20_util/reference_wrapper/typedefs-3.cc: Adjust to changes in _GLIBCXX_HAS_NESTED_TYPE. diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h index bd55987..ba3f923 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h @@ -64,7 +64,7 @@ #include #if __cplusplus >= 201103L -# include // For _GLIBCXX_HAS_NESTED_TYPE, is_convertible +# include // For __void_t, is_convertible #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -138,15 +138,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * provide tighter, more correct semantics. */ #if __cplusplus >= 201103L - -_GLIBCXX_HAS_NESTED_TYPE(iterator_category) - - template::value> + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14 + template> struct __iterator_traits { }; template - struct __iterator_traits<_Iterator, true> + struct __iterator_traits<_Iterator, + __void_t> { typedef typename _Iterator::iterator_category iterator_category; typedef typename _Iterator::value_type value_type; diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h index 7281508..a50ce10 100644 --- a/libstdc++-v3/include/bits/uses_allocator.h +++ b/libstdc++-v3/include/bits/uses_allocator.h @@ -40,15 +40,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr allocator_arg_t allocator_arg = allocator_arg_t(); -_GLIBCXX_HAS_NESTED_TYPE(allocator_type) - - template::value> + template> struct __uses_allocator_helper : false_type { }; template - struct __uses_allocator_helper<_Tp, _Alloc, true> + struct __uses_allocator_helper<_Tp, _Alloc, + __void_t> : is_convertible<_Alloc, typename _Tp::allocator_type>::type { }; diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 92489b7..e711350 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -67,24 +67,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Mem_fn<_Tp _Class::*> mem_fn(_Tp _Class::*) noexcept; -_GLIBCXX_HAS_NESTED_TYPE(result_type) - /// If we have found a result_type, extract it. - template + template> struct _Maybe_get_result_type { }; template - struct _Maybe_get_result_type + struct _Maybe_get_result_type<_Functor, + __void_t> { typedef typename _Functor::result_type result_type; }; /** * Base class for any function object that has a weak result type, as - * defined in 3.3/3 of TR1. + * defined in 20.8.2 [func.require] of C++11. */ template struct _Weak_result_type_impl - : _Maybe_get_result_type<__has_result_type<_Functor>::value, _Functor> + : _Maybe_get_result_type<_Functor> { }; /// Retrieve the result type for a function type. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index cecc7dc..6b72a3a 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2404,34 +2404,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using result_of_t = typename result_of<_Tp>::type; #endif + template using __void_t = void; + /// @} group metaprogramming - + /** * Use SFINAE to determine if the type _Tp has a publicly-accessible * member type _NTYPE. */ #define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ - template \ - class __has_##_NTYPE##_helper \ - { \ - template \ - struct _Wrap_type \ - { }; \ - \ - template \ - static true_type __test(_Wrap_type*); \ - \ - template \ - static false_type __test(...); \ - \ - public: \ - typedef decltype(__test<_Tp>(0)) type; \ - }; \ - \ - template \ + template> \ struct __has_##_NTYPE \ - : public __has_##_NTYPE##_helper \ - ::type>::type \ + : false_type \ + { }; \ + template \ + struct __has_##_NTYPE<_Tp, __void_t> \ + : true_type \ { }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc index 7810968..fde434f 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 *-*-* } 1126 } - // { dg-error "rvalue|const" "" { target *-*-* } 1140 } - // { dg-error "rvalue|const" "" { target *-*-* } 1154 } - // { dg-error "rvalue|const" "" { target *-*-* } 1168 } + // { dg-error "rvalue|const" "" { target *-*-* } 1125 } + // { dg-error "rvalue|const" "" { target *-*-* } 1139 } + // { dg-error "rvalue|const" "" { target *-*-* } 1153 } + // { dg-error "rvalue|const" "" { target *-*-* } 1167 } std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" } } diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc index 7d6a799..909b305 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc @@ -46,8 +46,7 @@ struct S012 : S0, S1, S2 { }; using std::true_type; using std::false_type; -using std::integral_constant; -using std::remove_cv; +using std::__void_t; _GLIBCXX_HAS_NESTED_TYPE(argument_type) _GLIBCXX_HAS_NESTED_TYPE(first_argument_type)