fork(2) download
  1. #include <iostream>
  2. #include <typeinfo>
  3.  
  4. using namespace std;
  5.  
  6.  
  7. /// Helper class to wrap incomplete types and avoid instantiation of T
  8. template<class T> struct Wrapper {};
  9.  
  10.  
  11. namespace CTList {
  12.  
  13. /// The front of compile-time lists
  14. struct Nil {};
  15.  
  16. } //namespace
  17.  
  18.  
  19. /// Compile-time list helper
  20. template< typename ListId, typename Item >
  21. Item NextInListHelper( ::Wrapper<ListId>, ::Wrapper<Item> );
  22.  
  23. #define Back(ListId) \
  24.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  25.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  26.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  27.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  28.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  29.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  30.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  31.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  32.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  33.   decltype( NextInListHelper( ::Wrapper<ListId>(), ::Wrapper<\
  34.   CTList::Nil \
  35.   >())) \
  36.   >())) \
  37.   >())) \
  38.   >())) \
  39.   >())) \
  40.   >())) \
  41.   >())) \
  42.   >())) \
  43.   >())) \
  44.   >()))
  45.  
  46.  
  47.  
  48. /// Add a new element (type) to the list
  49. #define PushBack( ListId, item) \
  50.   item NextInListHelper( ::Wrapper< ListId >, ::Wrapper< Back(ListId) > )
  51.  
  52. /// The next element in the ('ListId') list after 'item'
  53. #define Next(ListId, item) decltype(NextInListHelper(::Wrapper<ListId>(), ::Wrapper<item>() ))
  54.  
  55.  
  56.  
  57.  
  58. struct A {};
  59.  
  60.  
  61. namespace NS1 {
  62. struct B {};
  63. struct C {};
  64. struct D {};
  65.  
  66. // building up the compile-time list
  67. struct Head;
  68.  
  69. PushBack(Head, A);
  70. PushBack(Head, B);
  71.  
  72. }
  73.  
  74. PushBack(NS1::Head, NS1::C);
  75.  
  76. namespace NS1 {
  77. PushBack(Head, D);
  78. }
  79.  
  80.  
  81.  
  82. namespace NS2 {
  83.  
  84. // iterate through the list
  85. template <class ListId, class Item>
  86. void print(Wrapper<Item>, Wrapper<Item>) {}
  87.  
  88. template <class ListId, class PrevItem, class Item>
  89. void print(Wrapper<PrevItem>, Wrapper<Item>)
  90. {
  91. cout << typeid(Item).name() << endl;
  92. print<ListId>(Wrapper<Item>(), Wrapper< Next(ListId, Item) >());
  93. }
  94.  
  95. }
  96.  
  97.  
  98. #include <vector>
  99. #include <string>
  100.  
  101. namespace CTList {
  102.  
  103.  
  104. /// Helper for iterating through compile-time lists
  105. template<class ListId, class PrevItem, class Item>
  106. struct Iterator {};
  107.  
  108. /// Workaround for gcc's decltype():: bug
  109. template<class Iterator> struct IterTraits{};
  110. template<class ListId, class PrevItem, class Item>
  111. struct IterTraits<Iterator<ListId, PrevItem, Item>>
  112. {
  113. typedef ListId id;
  114. typedef Item item;
  115. typedef PrevItem prev;
  116.  
  117. };
  118.  
  119. }
  120.  
  121.  
  122. /// Iterator to the first element
  123. #define Begin(ListId) CTList::Iterator<ListId, CTList::Nil, Next(ListId, CTList::Nil)>()
  124.  
  125. /// Iterator to the next element after iterator @c it
  126. #define IteratorInc(it) \
  127.   CTList::Iterator< \
  128.   typename CTList::IterTraits<decltype(it)>::id, \
  129.   typename CTList::IterTraits<decltype(it)>::item, \
  130.   Next( \
  131.   typename CTList::IterTraits<decltype(it)>::id, \
  132.   typename CTList::IterTraits<decltype(it)>::item \
  133.   ) \
  134.   >()
  135.  
  136. namespace NS3 {
  137.  
  138. // iterating through the list with an 'iterator'
  139. template <class UserData, class ListId, class Item>
  140. void process(UserData&, CTList::Iterator<ListId, Item, Item> ) {}
  141.  
  142. template <class UserData, class ListId, class PrevItem, class Item>
  143. void process(UserData& u, CTList::Iterator<ListId, PrevItem, Item> it)
  144. {
  145. u.push_back(typeid(Item).name());
  146. process(u, IteratorInc(it));
  147. }
  148.  
  149. }
  150.  
  151. int main()
  152. {
  153. NS2::print<NS1::Head>(::Wrapper<CTList::Nil>(), ::Wrapper<Next(NS1::Head, CTList::Nil)>() );
  154.  
  155. vector<string> a, b = { typeid(A).name(), typeid(NS1::B).name() , typeid(NS1::C).name(), typeid(NS1::D).name() };
  156. NS3::process(a, Begin(NS1::Head));
  157. if (a == b) cout << "Passed!\n";
  158. return 0;
  159. }
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
Success #stdin #stdout 0s 3020KB
stdin
Standard input is empty
stdout
1A
N3NS11BE
N3NS11CE
N3NS11DE
Passed!