1 // { dg-do compile { target c++11 } }
2 // { dg-skip-if "argument_type removed for C++20" { c++2a } }
3 
4 // Copyright (C) 2011-2020 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3.  If not see
19 // <http://www.gnu.org/licenses/>.
20 
21 #include <functional>
22 #include <type_traits>
23 
24 struct S { };
25 
26 struct S0
27 {
28   typedef int argument_type;
29 };
30 
31 struct S1
32 {
33   typedef float first_argument_type;
34 };
35 
36 struct S2
37 {
38   typedef char second_argument_type;
39 };
40 
41 struct S01 : S0, S1 { };
42 struct S02 : S0, S2 { };
43 struct S12 : S1, S2 { };
44 
45 struct S012 : S0, S1, S2 { };
46 
47 using std::true_type;
48 using std::false_type;
49 using std::__void_t;
50 
51 _GLIBCXX_HAS_NESTED_TYPE(argument_type)
52 _GLIBCXX_HAS_NESTED_TYPE(first_argument_type)
53 _GLIBCXX_HAS_NESTED_TYPE(second_argument_type)
54 
55 template<typename T>
56   struct has_arg_type : __has_argument_type<T>
57   { };
58 
59 template<typename T>
60   struct has_1st_arg_type : __has_first_argument_type<T>
61   { };
62 
63 template<typename T>
64   struct has_2nd_arg_type : __has_second_argument_type<T>
65   { };
66 
67 template<typename T, bool = has_arg_type<T>::value>
68 struct test_arg_type
69 {
70   static_assert( !has_arg_type<std::reference_wrapper<T>>::value,
71       "reference_wrapper has no nested argument_type");
72 };
73 
74 template<typename T>
75 struct test_arg_type<T, true>
76 {
77   typedef std::reference_wrapper<T> ref;
78 
79   static_assert( has_arg_type<ref>::value,
80       "reference_wrapper has nested argument_type");
81 
82   static_assert(
83       std::is_same< typename T::argument_type,
84                     typename ref::argument_type >::value,
85       "reference_wrapper has the correct argument_type");
86 };
87 
88 template<typename T,
89          bool = has_1st_arg_type<T>::value && has_2nd_arg_type<T>::value>
90 struct test_1st_2nd_arg_types
91 {
92   typedef std::reference_wrapper<T> ref;
93 
94   static_assert( !has_1st_arg_type<ref>::value,
95       "reference_wrapper has no nested first_argument_type");
96 
97   static_assert( !has_2nd_arg_type<ref>::value,
98       "reference_wrapper has no nested second_argument_type");
99 };
100 
101 template<typename T>
102 struct test_1st_2nd_arg_types<T, true>
103 {
104   typedef std::reference_wrapper<T> ref;
105 
106   static_assert( has_1st_arg_type<ref>::value,
107       "reference_wrapper has nested first_argument_type");
108 
109   static_assert( has_2nd_arg_type<ref>::value,
110       "reference_wrapper has nested second_argument_type");
111 
112   static_assert(
113       std::is_same< typename T::first_argument_type,
114                     typename ref::first_argument_type>::value,
115       "reference_wrapper has correct first_argument_type");
116 
117   static_assert(
118       std::is_same< typename T::second_argument_type,
119                     typename ref::second_argument_type>::value,
120       "reference_wrapper has correct second_argument_type");
121 };
122 
123 
124 template<typename T>
test()125   void test()
126   {
127     test_arg_type<T> t __attribute__((unused));
128     test_arg_type<const T> tc __attribute__((unused));
129     test_arg_type<volatile T> tv __attribute__((unused));
130     test_arg_type<const volatile T> tcv __attribute__((unused));
131     test_1st_2nd_arg_types<T> t12 __attribute__((unused));
132     test_1st_2nd_arg_types<const T> t12c __attribute__((unused));
133     test_1st_2nd_arg_types<volatile T> t12v __attribute__((unused));
134     test_1st_2nd_arg_types<const volatile T> t12cv __attribute__((unused));
135   }
136 
main()137 int main()
138 {
139   test<S>();
140   test<S0>();
141   test<S1>();
142   test<S2>();
143   test<S01>();
144   test<S02>();
145   test<S12>();
146   test<S012>();
147 }
148 
149