1 // { dg-do compile { target c++11 } }
2 
3 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING3.  If not see
18 // <http://www.gnu.org/licenses/>.
19 
20 #include <type_traits>
21 
22 template<typename T, typename I0, typename... I>
23 struct smallest_rank
24 : std::conditional< sizeof(T) == sizeof(I0),
25                     I0,
26                     typename smallest_rank<T, I...>::type >
27 { };
28 
29 template<typename T, typename I0>
30 struct smallest_rank<T, I0>
31 { using type = I0; };
32 
33 template<typename T>
34 using smallest_rank_t
35   = typename smallest_rank<typename std::remove_cv<T>::type,
36                            signed char, signed short, signed int,
37                            signed long, signed long long>::type;
38 
39 using std::make_signed;
40 using std::is_same;
41 
42 enum E1 : char { };
43 using I1 = smallest_rank_t<E1>;
44 static_assert(is_same<make_signed<E1>::type,       I1>::value, "");
45 static_assert(is_same<make_signed<E1 const>::type, I1 const>::value, "");
46 
47 enum E2 : short { };
48 using I2 = smallest_rank_t<E2>;
49 static_assert(is_same<make_signed<E2>::type,       I2>::value, "");
50 static_assert(is_same<make_signed<E2 const>::type, I2 const>::value, "");
51 
52 enum E3 : int { };
53 using I3 = smallest_rank_t<E3>;
54 static_assert(is_same<make_signed<E3>::type,       I3>::value, "");
55 static_assert(is_same<make_signed<E3 const>::type, I3 const>::value, "");
56 
57 enum E4 : long { };
58 using I4 = smallest_rank_t<E4>;
59 static_assert(is_same<make_signed<E4>::type,       I4>::value, "");
60 static_assert(is_same<make_signed<E4 const>::type, I4 const>::value, "");
61 
62 // PR libstdc++/60333
63 enum E5 : long long { };
64 using I5 = smallest_rank_t<E5>;
65 static_assert(is_same<make_signed<E5>::type, I5>::value, "");
66 static_assert(is_same<make_signed<E5 const>::type, I5 const>::value, "");
67 
68 // PR libstdc++/85951
69 using I6 = smallest_rank_t<char16_t>;
70 static_assert(is_same<make_signed<char16_t>::type, I6>::value, "");
71 static_assert(is_same<make_signed<char16_t const>::type, I6 const>::value, "");
72 using I7 = smallest_rank_t<char32_t>;
73 static_assert(is_same<make_signed<char32_t>::type, I7>::value, "");
74 static_assert(is_same<make_signed<char32_t const>::type, I7 const>::value, "");
75 #ifdef _GLIBCXX_USE_WCHAR_T
76 using I8 = smallest_rank_t<wchar_t>;
77 static_assert(is_same<make_signed<wchar_t>::type, I8>::value, "");
78 static_assert(is_same<make_signed<wchar_t const>::type, I8 const>::value, "");
79 #endif
80