Synopsis - Cross-Reference

File: /tests/old_cxx_regressions/test-template.cc
  1// vim: set ts=8 sw=2 sts=2 et:
  2/* This file contains test cases for templates, taken from the C++ std.
  3 */
  4
  5// Comments out lines that are known to confuse the parser
  6#define FAIL(x)
  7
  8// Template parameter may be a class template
  9namespace Ex_14_1_1
 10{
 11  template<class T>
 12    class myarray
 13    { };
 14
 15  template<class K, class V, template<class T> class C = myarray>
 16    class Map
 17    {
 18      C<K> key;
 19      C<V> value;
 20    };
 21}
 22
 23// Prefer type-parameter over non-type template parameter
 24namespace Ex_14_1_2
 25{
 26  // A class named T to confuse the programmer
 27  class T { /* ... */ };
 28  int i;
 29
 30  // Here the template has a type-parameter 'T' rather than an unnamed
 31  // non-type template parameter of class T.
 32  // (A named non-type template parameter: "class T theT" or just "T theT")
 33  template<class T, T i>
 34    void f(T t)
 35    {
 36      T t1 = i;     // template parameters T and i
 37      ::T t2 = ::i; // global namespace members T and i
 38    }
 39}
 40
 41// Non-type non-reference template-parameter is not an lvalue
 42namespace Ex_14_1_5
 43{
 44  template<const X& x, int i>
 45    void f()
 46    {
 47      i++; // error: change of template-parameter value
 48
 49      &x; // ok
 50      &i; // error: address of non-reference template-parameter
 51
 52      int& ri = i; // error: non-const reference bound to temporary
 53      const int& cri = i; // ok: const reference bound to temporary
 54    }
 55}
 56
 57// Non-type template-parameter shall not be of void or floating type
 58namespace Ex_14_1_6
 59{
 60  template<double d> class X; // error
 61  template<double* pd> class Y; // ok
 62  template<double& rd> class Z; // ok
 63}
 64
 65// Array type decay does not apply to template-parameters
 66namespace Ex_14_1_7
 67{
 68  template<int a[5]>
 69    struct S
 70    { };
 71
 72  int v[5];
 73  int* p = v;
 74  S<v> x; // fine
 75  S<p> y; // error
 76}
 77
 78// Template-name followed by '<' is always template-id
 79namespace Ex_14_2_3
 80{
 81  template<int i>
 82    class X
 83    { };
 84
 85  FAIL( X<  1>2  > x1; )// syntax error
 86        X< (1>2) > x2;  // ok
 87
 88  template<class T>
 89    class Y
 90    { };
 91
 92  Y< X<1> >  x3; // ok
 93  Y< X< 6>>1 > > x4; // ok: Y< X< (6>>1) > >
 94}
 95
 96// Must use 'template' when '<' would otherwise mean 'less-than'
 97// ie, after '.' or '->' or after :: in a qualified-id that explicitly depends
 98// on a template-argument
 99namespace Ex_14_2_4
100{
101  class X
102  {
103  public:
104    template<size_t> X* alloc();
105  };
106
107  void f(X* p)
108  {
109    X* p1 = p->alloc<200>(); // ill-formed: < means less-than
110
111    X* p2 = p->template alloc<200>(); // fine: < starts explicit qualification
112  }
113}
114
115// Types of template-arguments in template-id shall match types in
116// template-parameter-list
117namespace Ex_14_3_1
118{
119  template<class T>
120    class Array
121    {
122      T* v;
123      int sz;
124    public:
125      explicit Array(int);
126      T& operator[](int);
127      T& elem(int i) { return v[i]; }
128    };
129
130  Array<int> v1(20);
131
132  template<class T>
133    class complex
134    {
135    public:
136      complex(T, T) { }
137    };
138  typedef complex<double> dcomplex;
139  
140  Array<dcomplex> v2(30);
141  Array<dcomplex> v3(40);
142
143  void f()
144  {
145    v1[3] = 7;
146    v2[3] = v3.elem(4) = dcomplex(7,8);
147  }
148}
149
150// Prefer type-id over expression in template-argument
151namespace Ex_14_3_2
152{
153  template<class T>
154    void f();
155
156  template<int i>
157    void f();
158
159  void g()
160  {
161    f<int()>(); // int() is a type-id: call the first f
162  }
163}
164
165// Template argument for non-type non-reference template-parameter shall not
166// be a string literal
167namespace Ex_14_3_3
168{
169  template<class T, char* p>
170    class X
171    {
172      X(const char* q) { }
173    };
174
175  X<int,"Studebaker"> x1; // error: string literal as template-argument
176
177  char p[] = "Vivi";
178  X<int,p> x2; // ok, p has external linkage
179}
180
181// Addresses of array elements and of non-static class members shall not be
182// used as template-arguments
183namespace Ex_14_3_4
184{
185  template<int* p>
186    class X
187    { };
188
189  int a[10];
190  struct S
191  {
192    int m;
193    static int s;
194  } s;
195
196  X<&a[2]> x3; // error: address of array element
197  X<&s.m> x4; // error: address of non-static member
198  X<&s.s> x5; // error: &S::s must be used
199  X<&S::s> x6; // ok: address of static member
200}
201
202// Non-type reference template-parameter has limitations on what it can be
203// bound to
204namespace Ex_14_3_5
205{
206  template<const int& CRI>
207    struct B
208    { };
209
210  B<1> b2; // error: temporary required for template argument
211
212  int c = 1;
213  B<c> b1; // ok
214}
215
216// Standard conversions used to turn template-argument into type of non-type
217// template-parameter
218namespace Ex_14_3_6
219{
220  template<const int* pci>
221    struct X
222    { };
223  int ai[10];
224  X<ai> x; // Array to pointer and qualification conversions
225
226  struct Base { };
227  struct Derived : Base { };
228  template<Base& b>
229    struct Y
230    { };
231  Derived d;
232  Y<d> yd; // derived to base conversion
233}
234
235// FuncPtr template argument must have exact type
236namespace Ex_14_3_7
237{
238  void f(char);
239  void f(int);
240
241  template<void (*pf)(int)>
242    struct A
243    { };
244
245  A<&f> a; // selects f(int)
246}
247
248// Declarations cannot become FuncPtr's because a FuncPtr is used as a
249// template-argument
250namespace Ex_14_3_8
251{
252  template<class T>
253    struct A
254    {
255      static T t;
256    };
257  typedef int function();
258  A<function> a; // ill-formed: would declare A<function>::t as a static member function
259}
260
261// Local, no-linkage and unnamed types cannot be used as template-arguments
262namespace Ex_14_3_9
263{
264  template<class T>
265    struct X {};
266  void f()
267  {
268    struct S
269    { };
270
271    X<S> x3; // error: local type used as template-argument
272  }
273}
274
275// Template follows normal access rules
276namespace Ex_14_3_10
277{
278  template<class T>
279    class X
280    { };
281
282  class Y
283  {
284  private:
285    struct S
286    { };
287
288    X<S> x; // ok: S is accessible
289  };
290
291  X<Y::S> y; // error: S not accessible
292}
293
294// Template-argument list is "<>" if all default arguments used
295namespace Ex_14_3_11
296{
297  template<class T = char>
298    class String;
299  String<>* p; // ok: String<char>
300  String* q; // syntax error
301}
302
303// May specify argument for destructor call
304namespace Ex_14_3_12
305{
306  template<class T>
307    struct A
308    {
309      ~A();
310    };
311
312  void main()
313  {
314    A<int>* p;
315    p->A<int>::~A(); // ok: destructor call
316    FAIL( p->A<int>::~A<int>(); ) // ok: destructor call
317  }
318}
319
320// Template-id's can refer to the same class or function
321// if they are the same
322namespace Ex_14_4_1
323{
324  template<class E, int size>
325    class buffer
326    { };
327
328  buffer<char, 2*512> x;
329  buffer<char, 1024> y; // same type as x
330
331  template<class T, void(*err_fct)()>
332    class list
333    { };
334  void error_handler1();
335  void error_handler2();
336  list<int, &error_handler1> x1;
337  list<int, &error_handler2> x2;
338  list<int, &error_handler2> x3; // same type as x2 but not x1 or x4
339  list<char,&error_handler2> x4;
340}
341
342// Template-id not specified in primary template declaration
343namespace Ex_14_5_1
344{
345  template<class T1, class T2, int I>
346    class A<T1, T2, I> // error!
347    { };
348
349  template<class T1, int I>
350    void sort<T1, I>(T1 data[I]); // error
351};
352
353// Can re-order template parameter names in method definition
354namespace Ex_14_5_1_3
355{
356  template<class T1, class T2>
357    struct A
358    {
359      void f1();
360      void f2();
361    };
362
363  template<class T2, class T1>
364    void A<T2,T1>::f1()
365    { } // ok
366
367  template<class T2, class T1>
368    void A<T1,T2>::f2()
369    { } // error
370}
371
372// Member function can be defined outside template
373namespace Ex_14_5_1_1_2
374{
375  template<class T>
376    class Array
377    {
378      T* v;
379      int sz;
380    public:
381      explicit Array(int);
382      T& operator[](int);
383      T& elem(int i) { return v[i]; }
384    };
385  // Three function templates declared above
386  
387  template<class T>
388    T& Array<T>::operator[](int i)
389    {
390      return v[i];
391    }
392}
393  
394// Template arguments for method taken from object type
395namespace Ex_14_5_1_1_3
396{
397  using Ex_14_5_1_1_2::Array;
398  using Ex_14_3_1::dcomplex;
399
400  void f()
401  {
402    Array<int> v1(20);
403    Array<dcomplex> v2(30);
404
405    v1[3] = 7; // Array<int>::operator[]();
406    v2[3] = dcomplex(7,8); // Array<dcomplex>::operator[]();
407  }
408}
409
410// Can define member class outside class, but before first use
411namespace Ex_14_5_1_2_2
412{
413  template<class T>
414    struct A
415    {
416      class B;
417    };
418
419  A<int>::B* b1; // ok: requires A to be defined but not A::B
420  template<class T>
421    class A<T>::B
422    { };
423  A<int>::B b2; // ok: requires A::B to be defined
424}
425