1 // PR c++/62134
2 // { dg-do compile { target c++11 } }
3 
4 template<typename... T> struct tuple;
5 template<__SIZE_TYPE__, typename U> struct tuple_element;
6 
7 template<bool, typename T = void> struct enable_if  { };
8 template<typename T> struct enable_if<true, T> { typedef T type; };
9 
10 template <int V> struct int_t { static constexpr int value = V; };
11 template <int V> int constexpr int_t<V>::value;
12 
13 template <class A, class Val, int i=0>
14 struct Index
15 {
16     static int const value = -1;
17 };
18 
19 template <class ... A, class Val, int i>
20 struct Index<tuple<Val, A ...>, Val, i>
21 {
22     static int const value = i;
23 };
24 
25 template <class A0, class ... A, class Val, int i>
26 struct Index<tuple<A0, A ...>, Val, i>
27 {
28     static int const value = Index<tuple<A ...>, Val, i+1>::value;
29 };
30 
31 template <class C, class R> struct PermutationSign;
32 
33 template <int w, class C, class R>
34 struct PermutationSignIfFound
35 {
36     static int const value = 0;
37 };
38 
39 template <class C, class R>
40 struct PermutationSignIfFound<-1, C, R>
41 {
42     static int const value = 0;
43 };
44 
45 template <>
46 struct PermutationSign<tuple<>, tuple<>>
47 {
48     static int const value = 1;
49 };
50 
51 template <class C>
52 struct PermutationSign<C, tuple<>>
53 {
54     static int const value = 0;
55 };
56 
57 template <class R>
58 struct PermutationSign<tuple<>, R>
59 {
60     static int const value = 0;
61 };
62 
63 template <class C, class Org>
64 struct PermutationSign
65 {
66     static int const value
67     = PermutationSignIfFound
68       <Index<C, typename tuple_element<0, Org>::type>::value,
69        C, Org>::value;
70 };
71 
72 template <class A, template <class> class Pred, int i=0, class Enable=void>
73 struct IndexIf
74 {
75     static int const value = -1;
76     using type = tuple<>;
77 };
78 
79 template <class A0, class ... A, template <class> class Pred, int i>
80 struct IndexIf<tuple<A0, A ...>, Pred, i,
81 	       typename enable_if<Pred<A0>::value>::type>
82 {
83     using type = A0;
84     static int const value = i;
85 };
86 
87 template <class A0, class ... A, template <class> class Pred, int i>
88 struct IndexIf<tuple<A0, A ...>, Pred, i,
89 	       typename enable_if<!Pred<A0>::value>::type>
90 {
91     using next = IndexIf<tuple<A ...>, Pred, i+1>;
92     using type = typename next::type;
93     static int const value = next::value;
94 };
95 
96 template <class P>
97 struct MatchPermutationP
98 {
99     template <class A> using type = PermutationSign<P, A>;
100 };
101 
102 template <class P, class Plist> struct FindCombination
103 {
104     using type = IndexIf<Plist, MatchPermutationP<P>::template type>;
105     static int const where = type::value;
106     static int const sign
107     = (where>=0) ? PermutationSign<P, typename type::type>::value : 0;
108 };
109 
110 int main()
111 {
112   using finder = FindCombination<tuple<>, tuple<tuple<>>>;
113   static_assert(finder::where==0 && finder::sign==+1, "bad");
114 }
115