1169691Skan// -*- C++ -*- 2169691Skan 3169691Skan// Copyright (C) 2005, 2006 Free Software Foundation, Inc. 4169691Skan// 5169691Skan// This file is part of the GNU ISO C++ Library. This library is free 6169691Skan// software; you can redistribute it and/or modify it under the 7169691Skan// terms of the GNU General Public License as published by the 8169691Skan// Free Software Foundation; either version 2, or (at your option) 9169691Skan// any later version. 10169691Skan 11169691Skan// This library is distributed in the hope that it will be useful, 12169691Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of 13169691Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14169691Skan// GNU General Public License for more details. 15169691Skan 16169691Skan// You should have received a copy of the GNU General Public License along 17169691Skan// with this library; see the file COPYING. If not, write to the Free 18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19169691Skan// USA. 20169691Skan 21169691Skan// As a special exception, you may use this file as part of a free software 22169691Skan// library without restriction. Specifically, if other files instantiate 23169691Skan// templates or use macros or inline functions from this file, or you compile 24169691Skan// this file and link it with other files to produce an executable, this 25169691Skan// file does not by itself cause the resulting executable to be covered by 26169691Skan// the GNU General Public License. This exception does not however 27169691Skan// invalidate any other reasons why the executable file might be covered by 28169691Skan// the GNU General Public License. 29169691Skan 30169691Skan// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. 31169691Skan 32169691Skan// Permission to use, copy, modify, sell, and distribute this software 33169691Skan// is hereby granted without fee, provided that the above copyright 34169691Skan// notice appears in all copies, and that both that copyright notice and 35169691Skan// this permission notice appear in supporting documentation. None of 36169691Skan// the above authors, nor IBM Haifa Research Laboratories, make any 37169691Skan// representation about the suitability of this software for any 38169691Skan// purpose. It is provided "as is" without express or implied warranty. 39169691Skan 40169691Skan/** 41169691Skan * @file typelist.h 42169691Skan * Contains typelist_chain definitions. 43169691Skan * Typelists are an idea by Andrei Alexandrescu. 44169691Skan */ 45169691Skan 46169691Skan#ifndef _TYPELIST_H 47169691Skan#define _TYPELIST_H 1 48169691Skan 49169691Skan#include <ext/type_traits.h> 50169691Skan 51169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 52169691Skan 53169691Skannamespace typelist 54169691Skan{ 55169691Skan struct null_type { }; 56169691Skan 57169691Skan template<typename Root> 58169691Skan struct node 59169691Skan { 60169691Skan typedef Root root; 61169691Skan }; 62169691Skan 63169691Skan // Forward declarations of functors. 64169691Skan template<typename Hd, typename Typelist> 65169691Skan struct chain 66169691Skan { 67169691Skan typedef Hd head; 68169691Skan typedef Typelist tail; 69169691Skan }; 70169691Skan 71169691Skan template<typename Fn, class Typelist> 72169691Skan void 73169691Skan apply(Fn&, Typelist); 74169691Skan 75169691Skan template<typename Typelist0, typename Typelist1> 76169691Skan struct append; 77169691Skan 78169691Skan template<typename Typelist_Typelist> 79169691Skan struct append_typelist; 80169691Skan 81169691Skan template<typename Typelist, typename T> 82169691Skan struct contains; 83169691Skan 84169691Skan template<typename Typelist, template<typename T> class Pred> 85169691Skan struct filter; 86169691Skan 87169691Skan template<typename Typelist, int i> 88169691Skan struct at_index; 89169691Skan 90169691Skan template<typename Typelist, template<typename T> class Transform> 91169691Skan struct transform; 92169691Skan 93169691Skan template<typename Typelist_Typelist> 94169691Skan struct flatten; 95169691Skan 96169691Skan template<typename Typelist> 97169691Skan struct from_first; 98169691Skan 99169691Skan template<typename T1> 100169691Skan struct create1; 101169691Skan 102169691Skan template<typename T1, typename T2> 103169691Skan struct create2; 104169691Skan 105169691Skan template<typename T1, typename T2, typename T3> 106169691Skan struct create3; 107169691Skan 108169691Skan template<typename T1, typename T2, typename T3, typename T4> 109169691Skan struct create4; 110169691Skan 111169691Skan template<typename T1, typename T2, typename T3, typename T4, typename T5> 112169691Skan struct create5; 113169691Skan 114169691Skan template<typename T1, typename T2, typename T3, 115169691Skan typename T4, typename T5, typename T6> 116169691Skan struct create6; 117169691Skan} // namespace typelist 118169691Skan 119169691Skan_GLIBCXX_END_NAMESPACE 120169691Skan 121169691Skan 122169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 123169691Skan 124169691Skannamespace typelist 125169691Skan{ 126169691Skannamespace detail 127169691Skan{ 128169691Skan template<typename Fn, typename Typelist_Chain> 129169691Skan struct apply_; 130169691Skan 131169691Skan template<typename Fn, typename Hd, typename Tl> 132169691Skan struct apply_<Fn, chain<Hd, Tl> > 133169691Skan { 134169691Skan void 135169691Skan operator() (Fn& f) 136169691Skan { 137169691Skan f.operator()(Hd()); 138169691Skan apply_<Fn, Tl> next; 139169691Skan next(f); 140169691Skan } 141169691Skan }; 142169691Skan 143169691Skan template<typename Fn> 144169691Skan struct apply_<Fn, null_type> 145169691Skan { 146169691Skan void 147169691Skan operator()(Fn&) { } 148169691Skan }; 149169691Skan 150169691Skan template<typename Typelist_Chain0, typename Typelist_Chain1> 151169691Skan struct append_; 152169691Skan 153169691Skan template<typename Hd, typename Tl, typename Typelist_Chain> 154169691Skan struct append_<chain<Hd, Tl>, Typelist_Chain> 155169691Skan { 156169691Skan private: 157169691Skan typedef append_<Tl, Typelist_Chain> append_type; 158169691Skan 159169691Skan public: 160169691Skan typedef chain<Hd, typename append_type::type> type; 161169691Skan }; 162169691Skan 163169691Skan template<typename Typelist_Chain> 164169691Skan struct append_<null_type, Typelist_Chain> 165169691Skan { 166169691Skan typedef Typelist_Chain type; 167169691Skan }; 168169691Skan 169169691Skan template<typename Typelist_Chain> 170169691Skan struct append_<Typelist_Chain, null_type> 171169691Skan { 172169691Skan typedef Typelist_Chain type; 173169691Skan }; 174169691Skan 175169691Skan template<> 176169691Skan struct append_<null_type, null_type> 177169691Skan { 178169691Skan typedef null_type type; 179169691Skan }; 180169691Skan 181169691Skan template<typename Typelist_Typelist_Chain> 182169691Skan struct append_typelist_; 183169691Skan 184169691Skan template<typename Hd> 185169691Skan struct append_typelist_<chain<Hd, null_type> > 186169691Skan { 187169691Skan typedef chain<Hd, null_type> type; 188169691Skan }; 189169691Skan 190169691Skan template<typename Hd, typename Tl> 191169691Skan struct append_typelist_<chain< Hd, Tl> > 192169691Skan { 193169691Skan private: 194169691Skan typedef typename append_typelist_<Tl>::type rest_type; 195169691Skan 196169691Skan public: 197169691Skan typedef typename append<Hd, node<rest_type> >::type::root type; 198169691Skan }; 199169691Skan 200169691Skan template<typename Typelist_Chain, typename T> 201169691Skan struct contains_; 202169691Skan 203169691Skan template<typename T> 204169691Skan struct contains_<null_type, T> 205169691Skan { 206169691Skan enum 207169691Skan { 208169691Skan value = false 209169691Skan }; 210169691Skan }; 211169691Skan 212169691Skan template<typename Hd, typename Tl, typename T> 213169691Skan struct contains_<chain<Hd, Tl>, T> 214169691Skan { 215169691Skan enum 216169691Skan { 217169691Skan value = contains_<Tl, T>::value 218169691Skan }; 219169691Skan }; 220169691Skan 221169691Skan template<typename Tl, typename T> 222169691Skan struct contains_<chain<T, Tl>, T> 223169691Skan { 224169691Skan enum 225169691Skan { 226169691Skan value = true 227169691Skan }; 228169691Skan }; 229169691Skan 230169691Skan template<typename Typelist_Chain, template<typename T> class Pred> 231169691Skan struct chain_filter_; 232169691Skan 233169691Skan template<template<typename T> class Pred> 234169691Skan struct chain_filter_<null_type, Pred> 235169691Skan { 236169691Skan typedef null_type type; 237169691Skan }; 238169691Skan 239169691Skan template<typename Hd, typename Tl, template<typename T> class Pred> 240169691Skan struct chain_filter_<chain<Hd, Tl>, Pred> 241169691Skan { 242169691Skan private: 243169691Skan enum 244169691Skan { 245169691Skan include_hd = Pred<Hd>::value 246169691Skan }; 247169691Skan 248169691Skan typedef typename chain_filter_<Tl, Pred>::type rest_type; 249169691Skan typedef chain<Hd, rest_type> chain_type; 250169691Skan 251169691Skan public: 252169691Skan typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type; 253169691Skan }; 254169691Skan 255169691Skan template<typename Typelist_Chain, int i> 256169691Skan struct chain_at_index_; 257169691Skan 258169691Skan template<typename Hd, typename Tl> 259169691Skan struct chain_at_index_<chain<Hd, Tl>, 0> 260169691Skan { 261169691Skan typedef Hd type; 262169691Skan }; 263169691Skan 264169691Skan template<typename Hd, typename Tl, int i> 265169691Skan struct chain_at_index_<chain<Hd, Tl>, i> 266169691Skan { 267169691Skan typedef typename chain_at_index_<Tl, i - 1>::type type; 268169691Skan }; 269169691Skan 270169691Skan template<class Typelist_Chain, template<typename T> class Transform> 271169691Skan struct chain_transform_; 272169691Skan 273169691Skan template<template<typename T> class Transform> 274169691Skan struct chain_transform_<null_type, Transform> 275169691Skan { 276169691Skan typedef null_type type; 277169691Skan }; 278169691Skan 279169691Skan template<class Hd, class Tl, template<typename T> class Transform> 280169691Skan struct chain_transform_<chain<Hd, Tl>, Transform> 281169691Skan { 282169691Skan private: 283169691Skan typedef typename chain_transform_<Tl, Transform>::type rest_type; 284169691Skan typedef typename Transform<Hd>::type transform_type; 285169691Skan 286169691Skan public: 287169691Skan typedef chain<transform_type, rest_type> type; 288169691Skan }; 289169691Skan 290169691Skan template<typename Typelist_Typelist_Chain> 291169691Skan struct chain_flatten_; 292169691Skan 293169691Skan template<typename Hd_Tl> 294169691Skan struct chain_flatten_<chain<Hd_Tl, null_type> > 295169691Skan { 296169691Skan typedef typename Hd_Tl::root type; 297169691Skan }; 298169691Skan 299169691Skan template<typename Hd_Typelist, class Tl_Typelist> 300169691Skan struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> > 301169691Skan { 302169691Skan private: 303169691Skan typedef typename chain_flatten_<Tl_Typelist>::type rest_type; 304169691Skan typedef append<Hd_Typelist, node<rest_type> > append_type; 305169691Skan public: 306169691Skan typedef typename append_type::type::root type; 307169691Skan }; 308169691Skan} // namespace detail 309169691Skan} // namespace typelist 310169691Skan 311169691Skan_GLIBCXX_END_NAMESPACE 312169691Skan 313169691Skan#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type> 314169691Skan#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) > 315169691Skan#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) > 316169691Skan#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) > 317169691Skan#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) > 318169691Skan#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) > 319169691Skan#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) > 320169691Skan#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) > 321169691Skan#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) > 322169691Skan#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) > 323169691Skan#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) > 324169691Skan#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) > 325169691Skan#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) > 326169691Skan#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) > 327169691Skan#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) > 328169691Skan 329169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 330169691Skan 331169691Skannamespace typelist 332169691Skan{ 333169691Skan template<typename Fn, class Typelist> 334169691Skan void 335169691Skan apply(Fn& fn, Typelist) 336169691Skan { 337169691Skan detail::apply_<Fn, typename Typelist::root> a; 338169691Skan a(fn); 339169691Skan } 340169691Skan 341169691Skan template<typename Typelist0, typename Typelist1> 342169691Skan struct append 343169691Skan { 344169691Skan private: 345169691Skan typedef typename Typelist0::root root0_type; 346169691Skan typedef typename Typelist1::root root1_type; 347169691Skan typedef detail::append_<root0_type, root1_type> append_type; 348169691Skan 349169691Skan public: 350169691Skan typedef node<typename append_type::type> type; 351169691Skan }; 352169691Skan 353169691Skan template<typename Typelist_Typelist> 354169691Skan struct append_typelist 355169691Skan { 356169691Skan private: 357169691Skan typedef typename Typelist_Typelist::root root_type; 358169691Skan typedef detail::append_typelist_<root_type> append_type; 359169691Skan 360169691Skan public: 361169691Skan typedef node<typename append_type::type> type; 362169691Skan }; 363169691Skan 364169691Skan template<typename Typelist, typename T> 365169691Skan struct contains 366169691Skan { 367169691Skan private: 368169691Skan typedef typename Typelist::root root_type; 369169691Skan 370169691Skan public: 371169691Skan enum 372169691Skan { 373169691Skan value = detail::contains_<root_type, T>::value 374169691Skan }; 375169691Skan }; 376169691Skan 377169691Skan template<typename Typelist, template<typename T> class Pred> 378169691Skan struct filter 379169691Skan { 380169691Skan private: 381169691Skan typedef typename Typelist::root root_type; 382169691Skan typedef detail::chain_filter_<root_type, Pred> filter_type; 383169691Skan 384169691Skan public: 385169691Skan typedef node<typename filter_type::type> type; 386169691Skan }; 387169691Skan 388169691Skan template<typename Typelist, int i> 389169691Skan struct at_index 390169691Skan { 391169691Skan private: 392169691Skan typedef typename Typelist::root root_type; 393169691Skan typedef detail::chain_at_index_<root_type, i> index_type; 394169691Skan 395169691Skan public: 396169691Skan typedef typename index_type::type type; 397169691Skan }; 398169691Skan 399169691Skan template<typename Typelist, template<typename T> class Transform> 400169691Skan struct transform 401169691Skan { 402169691Skan private: 403169691Skan typedef typename Typelist::root root_type; 404169691Skan typedef detail::chain_transform_<root_type, Transform> transform_type; 405169691Skan 406169691Skan public: 407169691Skan typedef node<typename transform_type::type> type; 408169691Skan }; 409169691Skan 410169691Skan template<typename Typelist_Typelist> 411169691Skan struct flatten 412169691Skan { 413169691Skan private: 414169691Skan typedef typename Typelist_Typelist::root root_type; 415169691Skan typedef typename detail::chain_flatten_<root_type>::type flatten_type; 416169691Skan 417169691Skan public: 418169691Skan typedef node<flatten_type> type; 419169691Skan }; 420169691Skan 421169691Skan template<typename Typelist> 422169691Skan struct from_first 423169691Skan { 424169691Skan private: 425169691Skan typedef typename at_index<Typelist, 0>::type first_type; 426169691Skan 427169691Skan public: 428169691Skan typedef node<chain<first_type, null_type> > type; 429169691Skan }; 430169691Skan 431169691Skan template<typename T1> 432169691Skan struct create1 433169691Skan { 434169691Skan typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; 435169691Skan }; 436169691Skan 437169691Skan template<typename T1, typename T2> 438169691Skan struct create2 439169691Skan { 440169691Skan typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; 441169691Skan }; 442169691Skan 443169691Skan template<typename T1, typename T2, typename T3> 444169691Skan struct create3 445169691Skan { 446169691Skan typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; 447169691Skan }; 448169691Skan 449169691Skan template<typename T1, typename T2, typename T3, typename T4> 450169691Skan struct create4 451169691Skan { 452169691Skan typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; 453169691Skan }; 454169691Skan 455169691Skan template<typename T1, typename T2, typename T3, 456169691Skan typename T4, typename T5> 457169691Skan struct create5 458169691Skan { 459169691Skan typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; 460169691Skan }; 461169691Skan 462169691Skan template<typename T1, typename T2, typename T3, 463169691Skan typename T4, typename T5, typename T6> 464169691Skan struct create6 465169691Skan { 466169691Skan typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; 467169691Skan }; 468169691Skan} // namespace typelist 469169691Skan_GLIBCXX_END_NAMESPACE 470169691Skan 471169691Skan 472169691Skan#endif 473169691Skan 474