1// -*- C++ -*- 2 3// Copyright (C) 2005, 2006 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 2, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// You should have received a copy of the GNU General Public License along 17// with this library; see the file COPYING. If not, write to the Free 18// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19// USA. 20 21// As a special exception, you may use this file as part of a free software 22// library without restriction. Specifically, if other files instantiate 23// templates or use macros or inline functions from this file, or you compile 24// this file and link it with other files to produce an executable, this 25// file does not by itself cause the resulting executable to be covered by 26// the GNU General Public License. This exception does not however 27// invalidate any other reasons why the executable file might be covered by 28// the GNU General Public License. 29 30// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. 31 32// Permission to use, copy, modify, sell, and distribute this software 33// is hereby granted without fee, provided that the above copyright 34// notice appears in all copies, and that both that copyright notice and 35// this permission notice appear in supporting documentation. None of 36// the above authors, nor IBM Haifa Research Laboratories, make any 37// representation about the suitability of this software for any 38// purpose. It is provided "as is" without express or implied warranty. 39 40/** 41 * @file typelist.h 42 * Contains typelist_chain definitions. 43 * Typelists are an idea by Andrei Alexandrescu. 44 */ 45 46#ifndef _TYPELIST_H 47#define _TYPELIST_H 1 48 49#include <ext/type_traits.h> 50 51_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 52 53namespace typelist 54{ 55 struct null_type { }; 56 57 template<typename Root> 58 struct node 59 { 60 typedef Root root; 61 }; 62 63 // Forward declarations of functors. 64 template<typename Hd, typename Typelist> 65 struct chain 66 { 67 typedef Hd head; 68 typedef Typelist tail; 69 }; 70 71 template<typename Fn, class Typelist> 72 void 73 apply(Fn&, Typelist); 74 75 template<typename Typelist0, typename Typelist1> 76 struct append; 77 78 template<typename Typelist_Typelist> 79 struct append_typelist; 80 81 template<typename Typelist, typename T> 82 struct contains; 83 84 template<typename Typelist, template<typename T> class Pred> 85 struct filter; 86 87 template<typename Typelist, int i> 88 struct at_index; 89 90 template<typename Typelist, template<typename T> class Transform> 91 struct transform; 92 93 template<typename Typelist_Typelist> 94 struct flatten; 95 96 template<typename Typelist> 97 struct from_first; 98 99 template<typename T1> 100 struct create1; 101 102 template<typename T1, typename T2> 103 struct create2; 104 105 template<typename T1, typename T2, typename T3> 106 struct create3; 107 108 template<typename T1, typename T2, typename T3, typename T4> 109 struct create4; 110 111 template<typename T1, typename T2, typename T3, typename T4, typename T5> 112 struct create5; 113 114 template<typename T1, typename T2, typename T3, 115 typename T4, typename T5, typename T6> 116 struct create6; 117} // namespace typelist 118 119_GLIBCXX_END_NAMESPACE 120 121 122_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 123 124namespace typelist 125{ 126namespace detail 127{ 128 template<typename Fn, typename Typelist_Chain> 129 struct apply_; 130 131 template<typename Fn, typename Hd, typename Tl> 132 struct apply_<Fn, chain<Hd, Tl> > 133 { 134 void 135 operator() (Fn& f) 136 { 137 f.operator()(Hd()); 138 apply_<Fn, Tl> next; 139 next(f); 140 } 141 }; 142 143 template<typename Fn> 144 struct apply_<Fn, null_type> 145 { 146 void 147 operator()(Fn&) { } 148 }; 149 150 template<typename Typelist_Chain0, typename Typelist_Chain1> 151 struct append_; 152 153 template<typename Hd, typename Tl, typename Typelist_Chain> 154 struct append_<chain<Hd, Tl>, Typelist_Chain> 155 { 156 private: 157 typedef append_<Tl, Typelist_Chain> append_type; 158 159 public: 160 typedef chain<Hd, typename append_type::type> type; 161 }; 162 163 template<typename Typelist_Chain> 164 struct append_<null_type, Typelist_Chain> 165 { 166 typedef Typelist_Chain type; 167 }; 168 169 template<typename Typelist_Chain> 170 struct append_<Typelist_Chain, null_type> 171 { 172 typedef Typelist_Chain type; 173 }; 174 175 template<> 176 struct append_<null_type, null_type> 177 { 178 typedef null_type type; 179 }; 180 181 template<typename Typelist_Typelist_Chain> 182 struct append_typelist_; 183 184 template<typename Hd> 185 struct append_typelist_<chain<Hd, null_type> > 186 { 187 typedef chain<Hd, null_type> type; 188 }; 189 190 template<typename Hd, typename Tl> 191 struct append_typelist_<chain< Hd, Tl> > 192 { 193 private: 194 typedef typename append_typelist_<Tl>::type rest_type; 195 196 public: 197 typedef typename append<Hd, node<rest_type> >::type::root type; 198 }; 199 200 template<typename Typelist_Chain, typename T> 201 struct contains_; 202 203 template<typename T> 204 struct contains_<null_type, T> 205 { 206 enum 207 { 208 value = false 209 }; 210 }; 211 212 template<typename Hd, typename Tl, typename T> 213 struct contains_<chain<Hd, Tl>, T> 214 { 215 enum 216 { 217 value = contains_<Tl, T>::value 218 }; 219 }; 220 221 template<typename Tl, typename T> 222 struct contains_<chain<T, Tl>, T> 223 { 224 enum 225 { 226 value = true 227 }; 228 }; 229 230 template<typename Typelist_Chain, template<typename T> class Pred> 231 struct chain_filter_; 232 233 template<template<typename T> class Pred> 234 struct chain_filter_<null_type, Pred> 235 { 236 typedef null_type type; 237 }; 238 239 template<typename Hd, typename Tl, template<typename T> class Pred> 240 struct chain_filter_<chain<Hd, Tl>, Pred> 241 { 242 private: 243 enum 244 { 245 include_hd = Pred<Hd>::value 246 }; 247 248 typedef typename chain_filter_<Tl, Pred>::type rest_type; 249 typedef chain<Hd, rest_type> chain_type; 250 251 public: 252 typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type; 253 }; 254 255 template<typename Typelist_Chain, int i> 256 struct chain_at_index_; 257 258 template<typename Hd, typename Tl> 259 struct chain_at_index_<chain<Hd, Tl>, 0> 260 { 261 typedef Hd type; 262 }; 263 264 template<typename Hd, typename Tl, int i> 265 struct chain_at_index_<chain<Hd, Tl>, i> 266 { 267 typedef typename chain_at_index_<Tl, i - 1>::type type; 268 }; 269 270 template<class Typelist_Chain, template<typename T> class Transform> 271 struct chain_transform_; 272 273 template<template<typename T> class Transform> 274 struct chain_transform_<null_type, Transform> 275 { 276 typedef null_type type; 277 }; 278 279 template<class Hd, class Tl, template<typename T> class Transform> 280 struct chain_transform_<chain<Hd, Tl>, Transform> 281 { 282 private: 283 typedef typename chain_transform_<Tl, Transform>::type rest_type; 284 typedef typename Transform<Hd>::type transform_type; 285 286 public: 287 typedef chain<transform_type, rest_type> type; 288 }; 289 290 template<typename Typelist_Typelist_Chain> 291 struct chain_flatten_; 292 293 template<typename Hd_Tl> 294 struct chain_flatten_<chain<Hd_Tl, null_type> > 295 { 296 typedef typename Hd_Tl::root type; 297 }; 298 299 template<typename Hd_Typelist, class Tl_Typelist> 300 struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> > 301 { 302 private: 303 typedef typename chain_flatten_<Tl_Typelist>::type rest_type; 304 typedef append<Hd_Typelist, node<rest_type> > append_type; 305 public: 306 typedef typename append_type::type::root type; 307 }; 308} // namespace detail 309} // namespace typelist 310 311_GLIBCXX_END_NAMESPACE 312 313#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type> 314#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) > 315#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) > 316#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) > 317#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) > 318#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) > 319#define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN6(X1, X2, X3, X4, X5, X6) > 320#define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN7(X1, X2, X3, X4, X5, X6, X7) > 321#define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN8(X1, X2, X3, X4, X5, X6, X7, X8) > 322#define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN9(X1, X2, X3, X4, X5, X6, X7, X8, X9) > 323#define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN10(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) > 324#define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN11(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) > 325#define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN12(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) > 326#define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN13(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) > 327#define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN14(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) > 328 329_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 330 331namespace typelist 332{ 333 template<typename Fn, class Typelist> 334 void 335 apply(Fn& fn, Typelist) 336 { 337 detail::apply_<Fn, typename Typelist::root> a; 338 a(fn); 339 } 340 341 template<typename Typelist0, typename Typelist1> 342 struct append 343 { 344 private: 345 typedef typename Typelist0::root root0_type; 346 typedef typename Typelist1::root root1_type; 347 typedef detail::append_<root0_type, root1_type> append_type; 348 349 public: 350 typedef node<typename append_type::type> type; 351 }; 352 353 template<typename Typelist_Typelist> 354 struct append_typelist 355 { 356 private: 357 typedef typename Typelist_Typelist::root root_type; 358 typedef detail::append_typelist_<root_type> append_type; 359 360 public: 361 typedef node<typename append_type::type> type; 362 }; 363 364 template<typename Typelist, typename T> 365 struct contains 366 { 367 private: 368 typedef typename Typelist::root root_type; 369 370 public: 371 enum 372 { 373 value = detail::contains_<root_type, T>::value 374 }; 375 }; 376 377 template<typename Typelist, template<typename T> class Pred> 378 struct filter 379 { 380 private: 381 typedef typename Typelist::root root_type; 382 typedef detail::chain_filter_<root_type, Pred> filter_type; 383 384 public: 385 typedef node<typename filter_type::type> type; 386 }; 387 388 template<typename Typelist, int i> 389 struct at_index 390 { 391 private: 392 typedef typename Typelist::root root_type; 393 typedef detail::chain_at_index_<root_type, i> index_type; 394 395 public: 396 typedef typename index_type::type type; 397 }; 398 399 template<typename Typelist, template<typename T> class Transform> 400 struct transform 401 { 402 private: 403 typedef typename Typelist::root root_type; 404 typedef detail::chain_transform_<root_type, Transform> transform_type; 405 406 public: 407 typedef node<typename transform_type::type> type; 408 }; 409 410 template<typename Typelist_Typelist> 411 struct flatten 412 { 413 private: 414 typedef typename Typelist_Typelist::root root_type; 415 typedef typename detail::chain_flatten_<root_type>::type flatten_type; 416 417 public: 418 typedef node<flatten_type> type; 419 }; 420 421 template<typename Typelist> 422 struct from_first 423 { 424 private: 425 typedef typename at_index<Typelist, 0>::type first_type; 426 427 public: 428 typedef node<chain<first_type, null_type> > type; 429 }; 430 431 template<typename T1> 432 struct create1 433 { 434 typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; 435 }; 436 437 template<typename T1, typename T2> 438 struct create2 439 { 440 typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; 441 }; 442 443 template<typename T1, typename T2, typename T3> 444 struct create3 445 { 446 typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; 447 }; 448 449 template<typename T1, typename T2, typename T3, typename T4> 450 struct create4 451 { 452 typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; 453 }; 454 455 template<typename T1, typename T2, typename T3, 456 typename T4, typename T5> 457 struct create5 458 { 459 typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; 460 }; 461 462 template<typename T1, typename T2, typename T3, 463 typename T4, typename T5, typename T6> 464 struct create6 465 { 466 typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; 467 }; 468} // namespace typelist 469_GLIBCXX_END_NAMESPACE 470 471 472#endif 473 474