Synopsis - Cross-Reference
File: /tests/old_cxx_regressions/test-template.cc1// 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