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.

From-SVN: r217395
This commit is contained in:
Jonathan Wakely 2014-11-11 23:57:35 +00:00 committed by Jonathan Wakely
parent 3c03d39d45
commit 847e9cf81e
7 changed files with 43 additions and 45 deletions

View File

@ -1,3 +1,14 @@
2014-11-11 Jonathan Wakely <jwakely@redhat.com>
* 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.
2014-11-11 Jonathan Wakely <jwakely@redhat.com>
* include/std/functional (_Mem_fn_traits): Add partial specializations

View File

@ -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;

View File

@ -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
{ };

View File

@ -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.

View File

@ -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

View File

@ -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" }
}

View File

@ -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)