1// { dg-options "-std=gnu++11" }
2// { dg-do compile }
3
4// Copyright (C) 2011-2015 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
24struct S { };
25
26struct S0
27{
28  typedef int argument_type;
29};
30
31struct S1
32{
33  typedef float first_argument_type;
34};
35
36struct S2
37{
38  typedef char second_argument_type;
39};
40
41struct S01 : S0, S1 { };
42struct S02 : S0, S2 { };
43struct S12 : S1, S2 { };
44
45struct S012 : S0, S1, S2 { };
46
47using std::true_type;
48using std::false_type;
49using 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
55template<typename T>
56  struct has_arg_type : __has_argument_type<T>
57  { };
58
59template<typename T>
60  struct has_1st_arg_type : __has_first_argument_type<T>
61  { };
62
63template<typename T>
64  struct has_2nd_arg_type : __has_second_argument_type<T>
65  { };
66
67template<typename T, bool = has_arg_type<T>::value>
68struct 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
74template<typename T>
75struct 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
88template<typename T,
89         bool = has_1st_arg_type<T>::value && has_2nd_arg_type<T>::value>
90struct 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
101template<typename T>
102struct 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
124template<typename T>
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
137int 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