From 83ddb39f042105cbb8861445c017062fe2c2d3a6 Mon Sep 17 00:00:00 2001 From: Daniel Krugler Date: Mon, 1 Oct 2012 16:02:57 +0000 Subject: [PATCH] type_traits (result_of): Provide "SFINAE-friendly" (see N3436) implementation. 2012-10-01 Daniel Krugler * include/std/type_traits (result_of): Provide "SFINAE-friendly" (see N3436) implementation. * testsuite/20_util/result_of/sfinae_friendly_1.cc: New. * testsuite/20_util/result_of/sfinae_friendly_2.cc: Likewise. * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Tweak dg-error line numbers. * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Likewise. * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. From-SVN: r191930 --- libstdc++-v3/ChangeLog | 12 + libstdc++-v3/include/std/type_traits | 203 ++++-- .../20_util/declval/requirements/1_neg.cc | 4 +- .../make_signed/requirements/typedefs_neg.cc | 17 +- .../make_unsigned/requirements/typedefs_neg.cc | 17 +- .../20_util/result_of/sfinae_friendly_1.cc | 736 +++++++++++++++++++++ .../20_util/result_of/sfinae_friendly_2.cc | 76 +++ 7 files changed, 984 insertions(+), 81 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_1.cc create mode 100644 libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_2.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 33a46cc..8fd82e7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2012-10-01 Daniel Krugler + + * include/std/type_traits (result_of): Provide "SFINAE-friendly" + (see N3436) implementation. + * testsuite/20_util/result_of/sfinae_friendly_1.cc: New. + * testsuite/20_util/result_of/sfinae_friendly_2.cc: Likewise. + * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Tweak + dg-error line numbers. + * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: + Likewise. + * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. + 2012-09-30 Benjamin Kosnik * doc/doxygen/user.cfg.in: Update to doxygen 1.8.2. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 9232af7..e8d432c 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1,7 +1,6 @@ // C++11 type_traits -*- C++ -*- -// Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 -// Free Software Foundation, Inc. +// Copyright (C) 2007-2012 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 @@ -1819,89 +1818,171 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class result_of; + // sfinae-friendly result_of implementation. We use enable_if to transport + // both the result information (as the member type) and the failure + // information (no member type). + + template + using __success_type = enable_if; + + using __failure_type = enable_if; + + // [func.require] paragraph 1 bullet 1: + struct __result_of_memfun_ref_impl + { + template + static __success_type().*std::declval<_Fp>())(std::declval<_Args>()...) + )> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_ref + : private __result_of_memfun_ref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; + }; + + // [func.require] paragraph 1 bullet 2: + struct __result_of_memfun_deref_impl + { + template + static __success_type()).*std::declval<_Fp>())(std::declval<_Args>()...) + )> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_deref + : private __result_of_memfun_deref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; + }; + + // [func.require] paragraph 1 bullet 3: + struct __result_of_memobj_ref_impl + { + template + static __success_type().*std::declval<_Fp>() + )> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_ref + : private __result_of_memobj_ref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; + }; + + // [func.require] paragraph 1 bullet 4: + struct __result_of_memobj_deref_impl + { + template + static __success_type()).*std::declval<_Fp>() + )> _S_test(int); + + template + static __failure_type _S_test(...); + }; + template - struct _Result_of_memobj; + struct __result_of_memobj_deref + : private __result_of_memobj_deref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; + }; + + template + struct __result_of_memobj; template - struct _Result_of_memobj<_Res _Class::*, _Arg> + struct __result_of_memobj<_Res _Class::*, _Arg> { - private: - typedef _Res _Class::* _Func; - - template - static _Tp _S_get(const _Class&); - template - static _Tp _S_get(const volatile _Class&); - template - static decltype(*std::declval<_Tp>()) _S_get(...); - - public: - typedef - decltype(_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>()) - __type; + typedef typename remove_cv::type>::type _Argval; + typedef _Res _Class::* _MemPtr; + typedef typename conditional<__or_, + is_base_of<_Class, _Argval>>::value, + __result_of_memobj_ref<_MemPtr, _Arg>, + __result_of_memobj_deref<_MemPtr, _Arg> + >::type::type type; }; - template - struct _Result_of_memfun; + template + struct __result_of_memfun; template - struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...> + struct __result_of_memfun<_Res _Class::*, _Arg, _Args...> { - private: - typedef _Res _Class::* _Func; - - template - static _Tp _S_get(const _Class&); - template - static _Tp _S_get(const volatile _Class&); - template - static decltype(*std::declval<_Tp>()) _S_get(...); - - public: - typedef - decltype((_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>()) - (std::declval<_Args>()...) ) - __type; + typedef typename remove_cv::type>::type _Argval; + typedef _Res _Class::* _MemPtr; + typedef typename conditional<__or_, + is_base_of<_Class, _Argval>>::value, + __result_of_memfun_ref<_MemPtr, _Arg, _Args...>, + __result_of_memfun_deref<_MemPtr, _Arg, _Args...> + >::type::type type; }; template - struct _Result_of_impl; - - template - struct _Result_of_impl + struct __result_of_impl { - typedef - decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) ) - __type; + typedef __failure_type type; }; template - struct _Result_of_impl - : _Result_of_memobj::type, _Arg> + struct __result_of_impl + : public __result_of_memobj::type, _Arg> { }; - template - struct _Result_of_impl - : _Result_of_memfun::type, _Arg, _ArgTypes...> + template + struct __result_of_impl + : public __result_of_memfun::type, _Arg, _Args...> { }; + // [func.require] paragraph 1 bullet 5: + struct __result_of_other_impl + { + template + static __success_type()(std::declval<_Args>()...) + )> _S_test(int); + + template + static __failure_type _S_test(...); + }; + template - struct result_of<_Functor(_ArgTypes...)> - : _Result_of_impl::type >::value, - is_member_function_pointer< - typename remove_reference<_Functor>::type >::value, - _Functor, _ArgTypes...> + struct __result_of_impl + : private __result_of_other_impl { - typedef typename _Result_of_impl< - is_member_object_pointer< - typename remove_reference<_Functor>::type >::value, - is_member_function_pointer< - typename remove_reference<_Functor>::type >::value, - _Functor, _ArgTypes...>::__type - type; + typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; }; + template + struct result_of<_Functor(_ArgTypes...)> + : public __result_of_impl< + is_member_object_pointer< + typename remove_reference<_Functor>::type + >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type + >::value, + _Functor, _ArgTypes... + >::type + { }; + /** * Use SFINAE to determine if the type _Tp has a publicly-accessible * member type _NTYPE. 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 2b6757e..6b9a4cb 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -2,7 +2,7 @@ // { dg-do compile } // 2009-11-12 Paolo Carlini // -// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. +// Copyright (C) 2009-2012 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 @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // . -// { dg-error "static assertion failed" "" { target *-*-* } 1813 } +// { dg-error "static assertion failed" "" { target *-*-* } 1812 } #include 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 1c68fac..3f1d33b 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 @@ -3,8 +3,7 @@ // 2007-05-03 Benjamin Kosnik // -// Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 -// Free Software Foundation, Inc. +// Copyright (C) 2007-2012 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 @@ -43,11 +42,11 @@ void test01() typedef make_signed::type test5_type; } -// { dg-error "does not name a type" "" { target *-*-* } 34 } -// { dg-error "required from here" "" { target *-*-* } 36 } -// { dg-error "required from here" "" { target *-*-* } 38 } -// { dg-error "required from here" "" { target *-*-* } 41 } -// { dg-error "required from here" "" { target *-*-* } 43 } +// { dg-error "does not name a type" "" { target *-*-* } 33 } +// { dg-error "required from here" "" { target *-*-* } 35 } +// { dg-error "required from here" "" { target *-*-* } 37 } +// { dg-error "required from here" "" { target *-*-* } 40 } +// { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1602 } -// { dg-error "declaration of" "" { target *-*-* } 1566 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1601 } +// { dg-error "declaration of" "" { target *-*-* } 1565 } 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 a41e5e6..b13200e 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 @@ -3,8 +3,7 @@ // 2007-05-03 Benjamin Kosnik // -// Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 -// Free Software Foundation, Inc. +// Copyright (C) 2007-2012 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 @@ -43,11 +42,11 @@ void test01() typedef make_unsigned::type test5_type; } -// { dg-error "does not name a type" "" { target *-*-* } 34 } -// { dg-error "required from here" "" { target *-*-* } 36 } -// { dg-error "required from here" "" { target *-*-* } 38 } -// { dg-error "required from here" "" { target *-*-* } 41 } -// { dg-error "required from here" "" { target *-*-* } 43 } +// { dg-error "does not name a type" "" { target *-*-* } 33 } +// { dg-error "required from here" "" { target *-*-* } 35 } +// { dg-error "required from here" "" { target *-*-* } 37 } +// { dg-error "required from here" "" { target *-*-* } 40 } +// { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1520 } -// { dg-error "declaration of" "" { target *-*-* } 1484 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1519 } +// { dg-error "declaration of" "" { target *-*-* } 1483 } diff --git a/libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_1.cc b/libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_1.cc new file mode 100644 index 0000000..3ea9e60 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_1.cc @@ -0,0 +1,736 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2012 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 +// . + +#include +#include +#include + +// TODO: Uncomment the following define once gcc has fixed bug 52748 +// (incomplete types in function call expressions): +//#define HAS_52748_FIXED + +// Helper types: +struct has_type_impl +{ + template + static std::true_type test(int); + + template + static std::false_type test(...); +}; + +template +struct has_type : decltype(has_type_impl::test(0)) +{}; + +template +struct is_expected_type : std::is_same +{}; + +template +struct is_type : std::__and_, is_expected_type> +{}; + +// Types under inspection: + +typedef bool (&PF1)(); +typedef short (*PF2)(long); + +struct S { + operator PF2() const; + double operator()(char, int&); + void calc(long) const; +}; + +typedef void (S::*PMS)(long) const; +typedef void (S::*PMSnonconst)(long); + +typedef int S::* PMI; + +struct B { + int i; + void f1() const; + bool f2(int) const volatile; +}; + +struct D : B {}; + +typedef void (B::*base_func_void)() const; +typedef bool (B::*base_func_bool_int)(int) const volatile; + +struct ident_functor { + template + T operator()(T&& x); +}; + +template +struct variable_functor { + template + Ret operator()(T&&...); +}; + +struct ident_functor_noref { + template + typename std::remove_reference::type operator()(T&& x); +}; + +enum class ScEn; + +enum UnScEn : int; + +union U { + int i; + double d; +}; + +union U2 { + int i; + bool b; + void operator()() const; + int operator()(double) const; + bool operator()(double); + U operator()(int, int); +}; + +struct Ukn; + +typedef Ukn (S::*PMSIncomplete)(long) const; +typedef Ukn (S::*PMSIncompletenonconst)(long); +typedef Ukn (*FuncIncomplete)(long); + +struct Abstract { + virtual ~Abstract() = 0; +}; + +struct Private { +private: + void operator()(); + int operator()(int); +public: + bool operator()(std::nullptr_t); +}; + +union PrivateUnion { + double d; +private: + void operator()(); + int operator()(int); +public: + bool operator()(std::nullptr_t); +}; + +template +struct ImplicitTo { + operator T(); +}; + +template +struct never { static const bool value = false; }; + +template +struct BrokenTrait { + static_assert(never::value, "Error!"); + typedef T type; +}; + +template +struct BadSmartPtr : T { + T& operator*() const noexcept(typename BrokenTrait::type()); +}; + +template +using FuncEllipses = Ret(...); + +static_assert(is_type, short>::value, "Error!"); +static_assert(is_type, + double>::value, "Error!"); +static_assert(is_type, bool>::value, "Error!"); +static_assert(is_type, bool>::value, "Error!"); +static_assert(is_type, int)>, + void>::value, "Error!"); +static_assert(is_type&, unsigned&)>, + void>::value, "Error!"); +static_assert(is_type, int)>, + void>::value, "Error!"); +static_assert(is_type&, unsigned&)>, + void>::value, "Error!"); + +static_assert(is_type, + int>::value, "Error!"); +static_assert(is_type, + int>::value, "Error!"); +static_assert(is_type, + int>::value, "Error!"); +static_assert(is_type, + int>::value, "Error!"); +static_assert(is_type, + int&>::value, "Error!"); + +static_assert(is_type, + B>::value, "Error!"); +static_assert(is_type, + const B>::value, "Error!"); +static_assert(is_type, B>::value, "Error!"); +static_assert(is_type, B&>::value, "Error!"); + +static_assert(is_type, int&>::value, "Error!"); + +// This is expected as of CWG 616 P/R: +static_assert(is_type, int&&>::value, "Error!"); + +static_assert(is_type, + const volatile int&&>::value, "Error!"); +static_assert(is_type, + const volatile int&&>::value, "Error!"); + +static_assert(is_type, + const int&>::value, "Error!"); +static_assert(is_type, + const volatile int&>::value, "Error!"); +static_assert(is_type, + const volatile int&>::value, "Error!"); + +static_assert(is_type, int&>::value, "Error!"); +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, + const int&>::value, "Error!"); +static_assert(is_type, + const int&>::value, "Error!"); +static_assert(is_type, + const volatile int&>::value, "Error!"); +static_assert(is_type, + const volatile int&>::value, "Error!"); + +static_assert(is_type, + void>::value, "Error!"); +static_assert(is_type, + void>::value, "Error!"); +static_assert(is_type, + void>::value, "Error!"); +static_assert(is_type, + void>::value, "Error!"); + +static_assert(!has_type>::value, + "Error!"); +static_assert(!has_type>::value, + "Error!"); + +static_assert(is_type, + bool>::value, "Error!"); +static_assert(is_type, + bool>::value, "Error!"); +static_assert(is_type, + bool>::value, "Error!"); +static_assert(is_type, + bool>::value, "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(is_type, short>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(is_type, short>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(is_type, int)>, void>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type)>>(), "Error!"); + +// Argument number mismatch: +static_assert(!has_type)>>(), "Error!"); +static_assert(!has_type&)>>(), "Error!"); +static_assert(!has_type, int, bool)>>(), + "Error!"); +static_assert(!has_type&, int, bool)>>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +// Non-convertible arguments: +static_assert(!has_type, S)>>(), + "Error!"); +static_assert(!has_type&, S)>>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +// cv-violations: +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); + +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, int&&>(), "Error!"); +static_assert(is_type, int&&>(), "Error!"); + +static_assert(!has_type>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +static_assert(is_type, int&&>(), "Error!"); +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, const int&>(), + "Error!"); +static_assert(is_type, const volatile int&>(), "Error!"); +static_assert(is_type, const volatile int&>(), "Error!"); + +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, int&&>(), "Error!"); +static_assert(is_type, const int&>(), + "Error!"); +static_assert(is_type, const int&>(), + "Error!"); +static_assert(is_type, const int&&>(), + "Error!"); + +typedef void (Ukn::* PUfnMF)(); +typedef void (Ukn::* PUfnConstMF)() const; + +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), + "Error!"); +static_assert(is_type, void>(), + "Error!"); +static_assert(is_type, void>(), + "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, bool>(), "Error!"); +static_assert(is_type, int>(), "Error!"); +static_assert(is_type, bool>(), "Error!"); +static_assert(is_type, bool>(), "Error!"); +static_assert(is_type, bool>(), "Error!"); +static_assert(is_type, int>(), "Error!"); +static_assert(is_type, U>(), "Error!"); +static_assert(is_type, U>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +static_assert(is_type, int>(), "Error!"); +static_assert(is_type, + int>(), "Error!"); +static_assert(is_type, int&>(), "Error!"); +static_assert(is_type, + const volatile int&>(), "Error!"); +static_assert(is_type, int>(), "Error!"); +static_assert(is_type, + int>(), "Error!"); +static_assert(is_type, Abstract&>(), + "Error!"); +static_assert(is_type, + const volatile Abstract&>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); + +// Border-line case: +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +// We want to allow this, it seems to be required by the order described +// in [func.require] p1: +static_assert(is_type&)>, int&>(), + "Error!"); + +static_assert(is_type, bool>(), + "Error!"); +static_assert(is_type, bool>(), + "Error!"); +static_assert(is_type, bool>(), + "Error!"); +static_assert(is_type)>, + bool>(), "Error!"); +static_assert(is_type)>, + bool>(), "Error!"); +static_assert(is_type)>, + bool>(), "Error!"); + +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type)>>(), "Error!"); +static_assert(!has_type)>>(), + "Error!"); +static_assert(!has_type)>>(), + "Error!"); +static_assert(!has_type)>>(), + "Error!"); + +static_assert(is_type, bool>(), + "Error!"); +static_assert(is_type, bool>(), + "Error!"); +static_assert(is_type, bool>(), + "Error!"); +static_assert(is_type)>, + bool>(), "Error!"); +static_assert(is_type)>, bool>(), "Error!"); +static_assert(is_type)>, bool>(), "Error!"); + +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type)>>(), + "Error!"); +static_assert(!has_type)>>(), + "Error!"); +static_assert(!has_type)>>(), "Error!"); +static_assert(!has_type)>>(), "Error!"); + +static_assert(is_type, void>(), "Error!"); +static_assert(is_type, void>(), "Error!"); +static_assert(is_type))(int)>, void>(), + "Error!"); +static_assert(is_type&))(int)>, void>(), + "Error!"); +static_assert(is_type&&))(int)>, void>(), + "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type&))(int)>>(), "Error!"); +static_assert(!has_type&&))(int)>>(), "Error!"); + +static_assert(is_type()>, void>(), + "Error!"); +static_assert(is_type()>, void>(), + "Error!"); + +static_assert(!has_type(int)>>(), + "Error!"); +static_assert(!has_type()>>(), + "Error!"); +static_assert(!has_type(int)>>(), + "Error!"); +static_assert(!has_type()>>(), + "Error!"); + +// Conversion operators of types are not considered in call expressions +// (except for conversion to function pointer/reference): +static_assert(!has_type(char, int&)>>(), "Error!"); +static_assert(!has_type(int)>>(), + "Error!"); + +static_assert(is_type()>, void>(), "Error!"); +static_assert(is_type(int)>, void>(), + "Error!"); +static_assert(is_type(int, int)>, void>(), + "Error!"); +static_assert(is_type(int, int, int)>, + void>(), "Error!"); + +static_assert(is_type&()>, void>(), "Error!"); +static_assert(is_type&(int)>, void>(), + "Error!"); +static_assert(is_type&(int, int)>, void>(), + "Error!"); +static_assert(is_type&(int, int, int)>, + void>(), "Error!"); + +static_assert(!has_type()>>(), + "Error!"); +static_assert(!has_type(int)>>(), + "Error!"); +static_assert(!has_type(int, int)>>(), + "Error!"); +static_assert(!has_type(int, int, int)>>(), "Error!"); + +static_assert(!has_type&()>>(), + "Error!"); +static_assert(!has_type&(int)>>(), + "Error!"); +static_assert(!has_type&(int, int)>>(), "Error!"); +static_assert(!has_type&(int, int, int)>>(), "Error!"); + +static_assert(is_type()>, S>(), "Error!"); +static_assert(is_type(int)>, S>(), "Error!"); +static_assert(is_type(int, int)>, S>(), + "Error!"); +static_assert(is_type(int, int, int)>, S>(), + "Error!"); + +static_assert(is_type&()>, S>(), "Error!"); +static_assert(is_type&(int)>, S>(), + "Error!"); +static_assert(is_type&(int, int)>, S>(), + "Error!"); +static_assert(is_type&(int, int, int)>, S>(), "Error!"); + +static_assert(!has_type()>>(), "Error!"); +static_assert(!has_type(int)>>(), "Error!"); +static_assert(!has_type(int, int)>>(), "Error!"); +static_assert(!has_type(int, int, int)>>(), "Error!"); + +static_assert(!has_type&()>>(), + "Error!"); +static_assert(!has_type&(int)>>(), + "Error!"); +static_assert(!has_type&(int, int)>>(), "Error!"); +static_assert(!has_type&(int, int, int)>>(), "Error!"); + +#if defined(HAS_52748_FIXED) +static_assert(has_type()>>(), "Error!"); +static_assert(is_type()>, Ukn>(), + "Error!"); +static_assert(is_type(int)>, Ukn>(), + "Error!"); +static_assert(is_type(int, int)>, Ukn>(), + "Error!"); +static_assert(is_type(int, int, int)>, Ukn>(), "Error!"); + +static_assert(is_type&()>, Ukn>(), + "Error!"); +static_assert(is_type&(int)>, Ukn>(), + "Error!"); +static_assert(is_type&(int, int)>, Ukn>(), "Error!"); +static_assert(is_type&(int, int, int)>, Ukn>(), "Error!"); + +static_assert(is_type, Ukn>(), "Error!"); +static_assert(is_type, Ukn>(), "Error!"); +static_assert(is_type, Ukn>(), "Error!"); + +static_assert(is_type, Ukn>(), "Error!"); +static_assert(is_type, Ukn>(), "Error!"); +static_assert(is_type, Ukn>(), "Error!"); + +static_assert(is_type*()>, Ukn>(), "Error!"); +static_assert(is_type&()>, Ukn>(), "Error!"); +static_assert(is_type&&()>, Ukn>(), "Error!"); + +static_assert(is_type*(bool)>, Ukn>(), + "Error!"); +static_assert(is_type&(bool)>, Ukn>(), + "Error!"); +static_assert(is_type&&(bool)>, Ukn>(), + "Error!"); + +static_assert(is_type*(bool, int, S)>, Ukn>(), + "Error!"); +static_assert(is_type&(bool, int, S)>, Ukn>(), + "Error!"); +static_assert(is_type&&(bool, int, S)>, Ukn>(), "Error!"); + +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +#endif + +static_assert(!has_type()>>(), + "Error!"); +static_assert(!has_type(int)>>(), + "Error!"); +static_assert(!has_type(int, int)>>(), "Error!"); +static_assert(!has_type(int, int, int)>>(), "Error!"); + +static_assert(!has_type&()>>(), + "Error!"); +static_assert(!has_type&(int)>>(), + "Error!"); +static_assert(!has_type&(int, int)>>(), "Error!"); +static_assert(!has_type&(int, int, int)>>(), "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); + +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), "Error!"); +static_assert(!has_type>(), + "Error!"); +static_assert(!has_type>(), + "Error!"); + +static_assert(is_type*()>, int>(), "Error!"); +static_assert(is_type&()>, int>(), "Error!"); +static_assert(is_type&&()>, int>(), "Error!"); + +static_assert(is_type*(bool)>, int>(), + "Error!"); +static_assert(is_type&(bool)>, int>(), + "Error!"); +static_assert(is_type&&(bool)>, int>(), + "Error!"); + +static_assert(is_type*(bool, int, S)>, int>(), + "Error!"); +static_assert(is_type&(bool, int, S)>, int>(), + "Error!"); +static_assert(is_type&&(bool, int, S)>, int>(), "Error!"); + diff --git a/libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_2.cc b/libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_2.cc new file mode 100644 index 0000000..57dcc5f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/result_of/sfinae_friendly_2.cc @@ -0,0 +1,76 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2012 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 +// . + +// Taken from N3436: + +#include +#include + +struct eat { template eat(T const &) {} }; +struct not_incrementable {}; + +struct inc { + template + auto operator()(T t) const -> decltype(t++) + { return t++; } +}; + +template +typename std::result_of::type // sfinae here +try_inc(A a) { + return inc()(a); +} + +not_incrementable +try_inc(eat) { + return not_incrementable(); +} + +template +struct never { static const bool value = false; }; + +template +struct Fail +{ + static_assert(never::value, "duh"); + typedef int type; +}; + +struct Fun +{ + template + typename Fail::type operator()(T) + { return 0; } +}; + +template +typename std::result_of::type foo(T) +{ return 0; } + +template +int foo(...) +{ return 0; } + +void result_of_sfinae() { + int x = try_inc(1); // OK + not_incrementable y = try_inc(std::string("foo")); // OK, not_incrementable + (void) x; + (void) y; +} -- 2.7.4