reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
template<typename T> struct X; // expected-note {{'X' is incomplete}}
template<int I> struct Y;

X<X<int>> *x1;

Y<(1 >> 2)> *y1;
Y<1 >> 2> *y2; // FIXME: expected-error{{expected unqualified-id}}

X<X<X<X<X<int>>>>> *x2;

template<> struct X<int> { };
typedef X<int> X_int;
struct Z : X_int { };

void f(const X<int> x) {
  (void)reinterpret_cast<X<int>>(x); // expected-error{{reinterpret_cast from}}
  (void)reinterpret_cast<X<X<X<int>>>>(x); // expected-error{{reinterpret_cast from}}

  X<X<int>> *x1;
}

template<typename T = void> struct X1 { };
X1<X1<>> x1a;


namespace ParameterPackExpansions {

// A template parameter pack that [contains an unexpanded parameter pack] is a
// pack expansion.

template<typename...Ts> struct Outer {
  // From [temp.variadic]p4:
  //   In a template parameter pack that is a pack expansion, the pattern is
  //   [...the template-parameter...] without the ellipsis.
  // Therefore the resulting sequence of parameters is not a parameter pack,
  // so is not required to be the last template parameter.
  template<Ts ...As, template<Ts> class ...Bs, typename ...Cs> struct Inner {
    struct Check : Bs<As>... {
      Check(Cs...);
    };
  };
};

template<int> struct TemplateInt {};
template<char> struct TemplateChar {};
template<int*> struct TemplateIntPtr {};
int x;

Outer<int, char, int*>::
Inner<12345, 'x', &x,
      TemplateInt, TemplateChar, TemplateIntPtr,
      int*>::
Check check(&x);


template<typename...Ts> struct types;

enum place { _ };
template<place...> struct places {};

template<typename P1, typename P2> struct append_places;
template<place...X1, place...X2>
struct append_places<places<X1...>, places<X2...>> {
  typedef places<X1...,X2...> type;
};

template<unsigned N>
struct make_places : append_places<typename make_places<N/2>::type,
                                   typename make_places<N-N/2>::type> {};
template<> struct make_places<0> { typedef places<> type; };
template<> struct make_places<1> { typedef places<_> type; };

template<typename T> struct wrap {
  template<place> struct inner { typedef T type; };
};

template<typename T> struct takedrop_impl;
template<place...X> struct takedrop_impl<places<X...>> {
  template<template<decltype(X)> class ...Take,
           template<place      > class ...Drop>
  struct inner { // expected-note 2{{declared}}
    typedef types<typename Take<_>::type...> take;
    typedef types<typename Drop<_>::type...> drop;
  };
};

template<unsigned N, typename...Ts> struct take {
  using type = typename takedrop_impl<typename make_places<N>::type>::
    template inner<wrap<Ts>::template inner...>::take; // expected-error {{too few template arguments}}
};
template<unsigned N, typename...Ts> struct drop {
  using type = typename takedrop_impl<typename make_places<N>::type>::
    template inner<wrap<Ts>::template inner...>::drop; // expected-error {{too few template arguments}}
};

using T1 = take<3, int, char, double, long>::type; // expected-note {{previous}}
// FIXME: Desguar the types on the RHS in this diagnostic.
// desired-error {{'types<void, void, void, void>' vs 'types<int, char, double, (no argument)>'}}
using T1 = types<void, void, void, void>; // expected-error {{'types<void, void, void, void>' vs 'types<typename inner<_>::type, typename inner<_>::type, typename inner<_>::type, (no argument)>'}}
using D1 = drop<3, int, char, double, long>::type;
using D1 = types<long>;

using T2 = take<4, int, char, double, long>::type; // expected-note {{previous}}
// FIXME: Desguar the types on the RHS in this diagnostic.
// desired-error {{'types<void, void, void, void>' vs 'types<int, char, double, long>'}}
using T2 = types<void, void, void, void>; // expected-error {{'types<void, void, void, void>' vs 'types<typename inner<_>::type, typename inner<_>::type, typename inner<_>::type, typename inner<_>::type>'}}
using T2 = types<int, char, double, long>;
using D2 = drop<4, int, char, double, long>::type;
using D2 = types<>;

using T3 = take<5, int, char, double, long>::type; // expected-note {{in instantiation of}}
using D3 = drop<5, int, char, double, long>::type; // expected-note {{in instantiation of}}


// FIXME: We should accept this code. A parameter pack within a default argument
// in a template template parameter pack is expanded, because the pack is
// implicitly a pack expansion.
template<typename ...Default> struct DefArg {
  template<template<typename T = Default> class ...Classes> struct Inner { // expected-error {{default argument contains unexpanded parameter pack}} expected-note {{here}}
    Inner(Classes<>...); // expected-error {{too few}}
  };
};
template<typename T> struct vector {};
template<typename T> struct list {};
vector<int> vi;
list<char> lc;
DefArg<int, char>::Inner<vector, list> defarg(vi, lc);


// FIXME:
// A template parameter pack that is a pack expansion shall not expand a
// parameter pack declared in the same template-parameter-list.
template<typename...Ts, Ts...Vs> void error(); // desired-error

// This case should not produce an error, because in A's instantiation, Cs is
// not a parameter pack.
template<typename...Ts> void consume(Ts...);
template<typename...Ts> struct A {
  template<template<typename, Ts = 0> class ...Cs, Cs<Ts> ...Vs> struct B { // ok
    B() {
      consume([]{
        int arr[Vs]; // expected-error {{negative size}}
      }...);
    }
  };
};
template<typename, int> using Int = int;
template<typename, short> using Char = char;
A<int, short>::B<Int, Char, -1, 'x'> b; // expected-note {{here}}

}

namespace PR9023 {
  template<typename ...T> struct A {
    template<template<T> class ...> struct B {
    };
  };

  template<int> struct C { };
  template<long> struct D { };

  int main() {
    A<int, long>::B<C, D> e;
  }
}

namespace std_examples {
  template <class... Types> class Tuple;
  template <class T, int... Dims> struct multi_array;
  template <class... T> struct value_holder {
    template<T... Values> struct apply { };
  };
  template <class... T, T... Values> struct static_array; // expected-error {{must be the last}}

  int n;
  value_holder<int, char, int*>::apply<12345, 'x', &n> test;
}