commit 57477dc54a9b74a3aaa8d50949d8aa7b23488a4c
Author: Jonathan Wakely <jwakely@redhat.com>
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.
@@ -64,7 +64,7 @@
#include <bits/c++config.h>
#if __cplusplus >= 201103L
-# include <type_traits> // For _GLIBCXX_HAS_NESTED_TYPE, is_convertible
+# include <type_traits> // 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<typename _Iterator,
- bool = __has_iterator_category<_Iterator>::value>
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14
+ template<typename _Iterator, typename = __void_t<>>
struct __iterator_traits { };
template<typename _Iterator>
- struct __iterator_traits<_Iterator, true>
+ struct __iterator_traits<_Iterator,
+ __void_t<typename _Iterator::iterator_category,
+ typename _Iterator::value_type,
+ typename _Iterator::difference_type,
+ typename _Iterator::pointer,
+ typename _Iterator::reference>>
{
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
@@ -40,15 +40,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
-_GLIBCXX_HAS_NESTED_TYPE(allocator_type)
-
- template<typename _Tp, typename _Alloc,
- bool = __has_allocator_type<_Tp>::value>
+ template<typename _Tp, typename _Alloc, typename = __void_t<>>
struct __uses_allocator_helper
: false_type { };
template<typename _Tp, typename _Alloc>
- struct __uses_allocator_helper<_Tp, _Alloc, true>
+ struct __uses_allocator_helper<_Tp, _Alloc,
+ __void_t<typename _Tp::allocator_type>>
: is_convertible<_Alloc, typename _Tp::allocator_type>::type
{ };
@@ -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<bool _Has_result_type, typename _Functor>
+ template<typename _Functor, typename = __void_t<>>
struct _Maybe_get_result_type
{ };
template<typename _Functor>
- struct _Maybe_get_result_type<true, _Functor>
+ struct _Maybe_get_result_type<_Functor,
+ __void_t<typename _Functor::result_type>>
{ 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<typename _Functor>
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.
@@ -2404,34 +2404,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using result_of_t = typename result_of<_Tp>::type;
#endif
+ template<typename...> 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<typename _Tp> \
- class __has_##_NTYPE##_helper \
- { \
- template<typename _Up> \
- struct _Wrap_type \
- { }; \
- \
- template<typename _Up> \
- static true_type __test(_Wrap_type<typename _Up::_NTYPE>*); \
- \
- template<typename _Up> \
- static false_type __test(...); \
- \
- public: \
- typedef decltype(__test<_Tp>(0)) type; \
- }; \
- \
- template<typename _Tp> \
+ template<typename _Tp, typename = __void_t<>> \
struct __has_##_NTYPE \
- : public __has_##_NTYPE##_helper \
- <typename remove_cv<_Tp>::type>::type \
+ : false_type \
+ { }; \
+ template<typename _Tp> \
+ struct __has_##_NTYPE<_Tp, __void_t<typename _Tp::_NTYPE>> \
+ : true_type \
{ };
_GLIBCXX_END_NAMESPACE_VERSION
@@ -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" }
}
@@ -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)