1 // Copyright (C) 2015-2021 Free Software Foundation, Inc. 2 // 3 // This file is part of the GNU ISO C++ Library. This library is free 4 // software; you can redistribute it and/or modify it under the 5 // terms of the GNU General Public License as published by the 6 // Free Software Foundation; either version 3, or (at your option) 7 // any later version. 8 9 // This library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 14 // You should have received a copy of the GNU General Public License along 15 // with this library; see the file COPYING3. If not see 16 // <http://www.gnu.org/licenses/>. 17 18 // { dg-do compile { target c++14 } } 19 20 #include <experimental/type_traits> 21 22 using std::declval; 23 using std::ptrdiff_t; 24 using std::experimental::is_detected; 25 using std::experimental::is_detected_exact; 26 using std::experimental::detected_or_t; 27 using std::experimental::is_same_v; 28 29 // Examples taken from N4502 30 31 // archetypal helper alias for a copy assignment operation: 32 template <class T> 33 using copy_assign_t = decltype(declval<T&>() = declval<T const &>()); 34 35 // plausible implementation for the is_assignable type trait: 36 template <class T> 37 using is_copy_assignable = is_detected<copy_assign_t, T>; 38 39 // plausible implementation for an augmented is_assignable type trait 40 // that also checks the return type: 41 template <class T> 42 using is_canonical_copy_assignable = is_detected_exact<T&, copy_assign_t, T>; 43 44 struct A { }; 45 struct B { B& operator=(const B&); }; 46 struct C { void operator=(const C&); }; 47 struct D { D& operator=(D&); }; 48 struct E { E& operator=(E&&); }; 49 50 static_assert( is_copy_assignable<A>::value, "A is copy assignable" ); 51 static_assert( is_copy_assignable<B>::value, "B is copy assignable" ); 52 static_assert( is_copy_assignable<C>::value, "C is copy assignable" ); 53 static_assert( !is_copy_assignable<D>::value, "D is not copy assignable" ); 54 static_assert( !is_copy_assignable<E>::value, "E is not copy assignable" ); 55 56 static_assert( is_canonical_copy_assignable<A>::value, 57 "A has canonical copy assignment" ); 58 static_assert( is_canonical_copy_assignable<B>::value, 59 "B has canonical copy assignment" ); 60 static_assert( !is_canonical_copy_assignable<C>::value, 61 "C does not have canonical copy assignment" ); 62 static_assert( !is_canonical_copy_assignable<D>::value, 63 "D does not have canonical copy assignment" ); 64 static_assert( !is_canonical_copy_assignable<E>::value, 65 "E does not have canonical copy assignment" ); 66 67 // archetypal helper alias for a particular type member: 68 template <class T> 69 using diff_t = typename T::difference_type; 70 // alias the type member, if it exists, otherwise alias ptrdiff_t: 71 template <class Ptr> 72 using difference_type = detected_or_t<ptrdiff_t, diff_t, Ptr>; 73 74 struct has { using difference_type = char; }; 75 struct has_not { }; 76 struct inherits : has { }; 77 struct hides : private has { }; 78 struct reveals : private has { using has::difference_type; }; 79 80 static_assert( is_same_v<difference_type<has>, char>, "has" ); 81 static_assert( is_same_v<difference_type<has_not>, ptrdiff_t>, "has not" ); 82 static_assert( is_same_v<difference_type<inherits>, char>, "inherits" ); 83 static_assert( is_same_v<difference_type<hides>, ptrdiff_t>, "hides" ); 84 static_assert( is_same_v<difference_type<reveals>, char>, "reveals" ); 85