#include <utility>
#include <cassert>
#include <cstddef>
#include <tuple>
template < class ... Types >
class type_list { } ;
template < std:: size_t idx, class ... Types >
class extract
{
static_assert( idx < sizeof ...( Types) , "index out of bounds" ) ;
template < std:: size_t i, std:: size_t n, class ... Rest >
struct extract_impl;
template < std:: size_t i, std:: size_t n, class T, class ... Rest >
struct extract_impl< i, n, T, Rest...>
{
using type = typename extract_impl< i + 1 , n, Rest...> :: type ;
} ;
template < std:: size_t n, class T, class ... Rest >
struct extract_impl< n, n, T, Rest...>
{
using type = T;
} ;
public :
using type = typename extract_impl< 0 , idx, Types...> :: type ;
} ;
template < std:: size_t idx, class TypeList>
struct type_list_extract;
template < std:: size_t idx, template < class ...> class TypeList, class ... Types >
struct type_list_extract< idx, TypeList< Types...>>
{
using type = typename extract< idx, Types...> :: type ;
} ;
template < std:: size_t idx, class TypeList>
using type_list_extract_t = typename type_list_extract< idx, TypeList> :: type ;
template < class FirstTypeList, class SecondTypeList>
struct type_list_concat;
template < template < class ...> class TypeList, class ... FirstTypesPack , class ... SecondTypesPack >
struct type_list_concat< TypeList< FirstTypesPack...> , TypeList< SecondTypesPack...> >
{
using type = TypeList< FirstTypesPack..., SecondTypesPack...> ;
} ;
template < class FirstTypeList, class SecondTypeList>
using type_list_concat_t = typename type_list_concat< FirstTypeList, SecondTypeList> :: type ;
template < class TypeList, size_t ... indexes >
struct type_list_expand
{
using type = std:: tuple < typename type_list_extract< indexes, TypeList> :: type ...> ;
} ;
template < template < class ...> class TypeList, class ... Types >
struct type_list_expand< TypeList< Types...>>
{
using type = std:: tuple < Types...> ;
} ;
template < class TypeList, size_t ... indexes >
using type_list_expand_t = typename type_list_expand< TypeList, indexes...> :: type ;
template < std:: size_t ... indexes >
struct first_index_holder;
template < std:: size_t head, std:: size_t ... remainder >
struct first_index_holder< head, remainder...>
{
static const std:: size_t value = head;
} ;
template < class IndexInterval>
class reverse_index_interval;
template < template < typename T, T ...> class IndexInterval, std:: size_t ... indexes >
class reverse_index_interval < IndexInterval< std:: size_t , indexes...>>
{
static const std:: size_t size = sizeof ...( indexes) - 1 ;
static const std:: size_t head = first_index_holder< indexes...> :: value ;
public :
using type = IndexInterval< std:: size_t , ( size + head - indexes + head) ... > ;
} ;
template < class TypeList>
class type_list_reverse;
template < template < class ... > class TypeList, class ... Types >
class type_list_reverse< TypeList< Types...> >
{
template < class integer_sequence, class TList>
struct typelist_reverse_impl;
template < template < typename T, T ...> class Sequence, std:: size_t ... indexes , template < class ...> class TList, class ... Ts >
struct typelist_reverse_impl< Sequence< std:: size_t , indexes...> , TList< Ts...>>
{
using type = TList< type_list_extract_t< indexes, TList< Ts...>> ...> ;
} ;
public :
using type = typename typelist_reverse_impl< typename reverse_index_interval< std:: make_index_sequence < sizeof ...( Types) > > :: type , TypeList< Types...>> :: type ;
} ;
template < class TypeList>
using type_list_reverse_t = typename type_list_reverse< TypeList> :: type ;
#include <utility>
#include <cassert>
//just to populate with some types
struct String;
struct Condition;
struct Opinion;
int main( )
{
using MyList = type_list< int , char , bool > ;
using First = type_list_extract_t< 0 , MyList> ;
static_assert( std:: is_same < First, int > :: value , "!" ) ;
using SecondList = type_list< String, Condition, Opinion> ;
using Concat = type_list_concat_t< MyList, SecondList> ;
static_assert( std:: is_same < type_list< int , char , bool , String, Condition, Opinion> , Concat> :: value , "!" ) ;
using Expansion = type_list_expand_t< MyList> ;
static_assert( std:: is_same < std:: tuple < int , char , bool > , Expansion> :: value , "!" ) ;
using PartialExpansion = type_list_expand_t< MyList, 0 , 2 > ; //int, bool
static_assert( std:: is_same < std:: tuple < int , bool > , PartialExpansion> :: value , "!" ) ;
constexpr std:: size_t sz = first_index_holder< 2 , 3 , 4 > :: value ;
static_assert( sz == 2 , "!" ) ;
using Seq = std:: index_sequence < 2 , 3 , 4 > ;
using ReversedSeq = reverse_index_interval< Seq> :: type ;
static_assert( std:: is_same < ReversedSeq, std:: index_sequence < 4 , 3 , 2 > > :: value , "!" ) ;
using Rev = type_list_reverse_t< MyList> ;
static_assert( std:: is_same < type_list< bool , char , int > , Rev> :: value , "!" ) ;
}
I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxjYXNzZXJ0PgojaW5jbHVkZSA8Y3N0ZGRlZj4KI2luY2x1ZGUgPHR1cGxlPgoKdGVtcGxhdGUgPGNsYXNzIC4uLiBUeXBlcz4KY2xhc3MgdHlwZV9saXN0IHt9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IGlkeCwgY2xhc3MuLi4gVHlwZXM+CmNsYXNzIGV4dHJhY3QKewoJc3RhdGljX2Fzc2VydChpZHggPCBzaXplb2YuLi4oVHlwZXMpLCAiaW5kZXggb3V0IG9mIGJvdW5kcyIpOwoKCXRlbXBsYXRlIDxzdGQ6OnNpemVfdCBpLCBzdGQ6OnNpemVfdCBuLCBjbGFzcy4uLiBSZXN0PgoJc3RydWN0IGV4dHJhY3RfaW1wbDsKCgl0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgaSwgc3RkOjpzaXplX3QgbiwgY2xhc3MgVCwgY2xhc3MuLi4gUmVzdD4KCXN0cnVjdCBleHRyYWN0X2ltcGw8aSwgbiwgVCwgUmVzdC4uLj4KCXsKCQl1c2luZyB0eXBlID0gdHlwZW5hbWUgZXh0cmFjdF9pbXBsPGkgKyAxLCBuLCBSZXN0Li4uPjo6dHlwZTsKCX07CgoJdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IG4sIGNsYXNzIFQsIGNsYXNzLi4uIFJlc3Q+CglzdHJ1Y3QgZXh0cmFjdF9pbXBsPG4sIG4sIFQsIFJlc3QuLi4+Cgl7CgkJdXNpbmcgdHlwZSA9IFQ7Cgl9OwpwdWJsaWM6Cgl1c2luZyB0eXBlID0gdHlwZW5hbWUgZXh0cmFjdF9pbXBsPDAsIGlkeCwgVHlwZXMuLi4+Ojp0eXBlOwp9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IGlkeCwgY2xhc3MgVHlwZUxpc3Q+CnN0cnVjdCB0eXBlX2xpc3RfZXh0cmFjdDsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBpZHgsIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgVHlwZUxpc3QsIGNsYXNzLi4uIFR5cGVzPgpzdHJ1Y3QgdHlwZV9saXN0X2V4dHJhY3Q8aWR4LCBUeXBlTGlzdDxUeXBlcy4uLj4+CnsKCXVzaW5nIHR5cGUgPSB0eXBlbmFtZSBleHRyYWN0PGlkeCwgVHlwZXMuLi4+Ojp0eXBlOwp9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IGlkeCwgY2xhc3MgVHlwZUxpc3Q+CnVzaW5nIHR5cGVfbGlzdF9leHRyYWN0X3QgPSB0eXBlbmFtZSB0eXBlX2xpc3RfZXh0cmFjdDxpZHgsIFR5cGVMaXN0Pjo6dHlwZTsKCnRlbXBsYXRlIDxjbGFzcyBGaXJzdFR5cGVMaXN0LCBjbGFzcyBTZWNvbmRUeXBlTGlzdD4Kc3RydWN0IHR5cGVfbGlzdF9jb25jYXQ7Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPGNsYXNzIC4uLj4gY2xhc3MgVHlwZUxpc3QsIGNsYXNzIC4uLiBGaXJzdFR5cGVzUGFjaywgY2xhc3MgLi4uIFNlY29uZFR5cGVzUGFjaz4Kc3RydWN0IHR5cGVfbGlzdF9jb25jYXQ8VHlwZUxpc3Q8Rmlyc3RUeXBlc1BhY2suLi4+LCBUeXBlTGlzdDxTZWNvbmRUeXBlc1BhY2suLi4+ID4KewoJdXNpbmcgdHlwZSA9IFR5cGVMaXN0PEZpcnN0VHlwZXNQYWNrLi4uLCBTZWNvbmRUeXBlc1BhY2suLi4+Owp9OwoKdGVtcGxhdGUgPGNsYXNzIEZpcnN0VHlwZUxpc3QsIGNsYXNzIFNlY29uZFR5cGVMaXN0Pgp1c2luZyB0eXBlX2xpc3RfY29uY2F0X3QgPSB0eXBlbmFtZSB0eXBlX2xpc3RfY29uY2F0PEZpcnN0VHlwZUxpc3QsIFNlY29uZFR5cGVMaXN0Pjo6dHlwZTsKCnRlbXBsYXRlIDxjbGFzcyBUeXBlTGlzdCwgc2l6ZV90IC4uLiBpbmRleGVzPgpzdHJ1Y3QgdHlwZV9saXN0X2V4cGFuZAp7Cgl1c2luZyB0eXBlID0gc3RkOjp0dXBsZTx0eXBlbmFtZSB0eXBlX2xpc3RfZXh0cmFjdDxpbmRleGVzLCBUeXBlTGlzdD46OnR5cGUuLi4+Owp9OwoKdGVtcGxhdGUgPCB0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIFR5cGVMaXN0LCBjbGFzcyAuLi4gVHlwZXM+CnN0cnVjdCB0eXBlX2xpc3RfZXhwYW5kPCBUeXBlTGlzdDxUeXBlcy4uLj4+CnsKCXVzaW5nIHR5cGUgPSBzdGQ6OnR1cGxlPFR5cGVzLi4uPjsKfTsKCnRlbXBsYXRlIDxjbGFzcyBUeXBlTGlzdCwgc2l6ZV90IC4uLiBpbmRleGVzPgp1c2luZyB0eXBlX2xpc3RfZXhwYW5kX3QgPSB0eXBlbmFtZSB0eXBlX2xpc3RfZXhwYW5kPFR5cGVMaXN0LCBpbmRleGVzLi4uPjo6dHlwZTsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCAuLi4gaW5kZXhlcz4Kc3RydWN0IGZpcnN0X2luZGV4X2hvbGRlcjsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBoZWFkLCBzdGQ6OnNpemVfdCAuLi4gcmVtYWluZGVyPgpzdHJ1Y3QgZmlyc3RfaW5kZXhfaG9sZGVyPGhlYWQsIHJlbWFpbmRlci4uLj4KewoJc3RhdGljIGNvbnN0IHN0ZDo6c2l6ZV90IHZhbHVlID0gaGVhZDsKfTsKCnRlbXBsYXRlIDxjbGFzcyBJbmRleEludGVydmFsPgpjbGFzcyByZXZlcnNlX2luZGV4X2ludGVydmFsOwoKdGVtcGxhdGUgPHRlbXBsYXRlIDx0eXBlbmFtZSBULCBUIC4uLj4gY2xhc3MgSW5kZXhJbnRlcnZhbCwgc3RkOjpzaXplX3QgLi4uIGluZGV4ZXM+CmNsYXNzIHJldmVyc2VfaW5kZXhfaW50ZXJ2YWwgPCBJbmRleEludGVydmFsPHN0ZDo6c2l6ZV90LCBpbmRleGVzLi4uPj4KewoJc3RhdGljIGNvbnN0IHN0ZDo6c2l6ZV90IHNpemUgPSBzaXplb2YuLi4oaW5kZXhlcyktMTsKCXN0YXRpYyBjb25zdCBzdGQ6OnNpemVfdCBoZWFkID0gZmlyc3RfaW5kZXhfaG9sZGVyPGluZGV4ZXMuLi4+Ojp2YWx1ZTsKcHVibGljOgoJdXNpbmcgdHlwZSA9IEluZGV4SW50ZXJ2YWw8c3RkOjpzaXplX3QsIChzaXplICsgaGVhZCAtIGluZGV4ZXMgKyBoZWFkKS4uLiA+Owp9OwoKdGVtcGxhdGUgPGNsYXNzIFR5cGVMaXN0PgpjbGFzcyB0eXBlX2xpc3RfcmV2ZXJzZTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8Y2xhc3MgLi4uID4gY2xhc3MgVHlwZUxpc3QsIGNsYXNzIC4uLiBUeXBlcz4KY2xhc3MgdHlwZV9saXN0X3JldmVyc2U8VHlwZUxpc3Q8VHlwZXMuLi4+ID4KewoJdGVtcGxhdGUgPGNsYXNzIGludGVnZXJfc2VxdWVuY2UsIGNsYXNzIFRMaXN0PgoJc3RydWN0IHR5cGVsaXN0X3JldmVyc2VfaW1wbDsKCgl0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lIFQsIFQgLi4uPiBjbGFzcyBTZXF1ZW5jZSwgc3RkOjpzaXplX3QgLi4uIGluZGV4ZXMsIHRlbXBsYXRlPGNsYXNzIC4uLj4gY2xhc3MgVExpc3QsIGNsYXNzIC4uLiBUcz4KCXN0cnVjdCB0eXBlbGlzdF9yZXZlcnNlX2ltcGw8U2VxdWVuY2U8c3RkOjpzaXplX3QsIGluZGV4ZXMuLi4+LCBUTGlzdDxUcy4uLj4+Cgl7CgkJdXNpbmcgdHlwZSA9IFRMaXN0PHR5cGVfbGlzdF9leHRyYWN0X3Q8aW5kZXhlcywgVExpc3Q8VHMuLi4+Pi4uLj47Cgl9OwpwdWJsaWM6Cgl1c2luZyB0eXBlID0gdHlwZW5hbWUgdHlwZWxpc3RfcmV2ZXJzZV9pbXBsPHR5cGVuYW1lIHJldmVyc2VfaW5kZXhfaW50ZXJ2YWw8c3RkOjptYWtlX2luZGV4X3NlcXVlbmNlPHNpemVvZi4uLihUeXBlcyk+ID46OnR5cGUsIFR5cGVMaXN0PFR5cGVzLi4uPj46OnR5cGU7Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgVHlwZUxpc3Q+CnVzaW5nIHR5cGVfbGlzdF9yZXZlcnNlX3QgPSB0eXBlbmFtZSB0eXBlX2xpc3RfcmV2ZXJzZTxUeXBlTGlzdD46OnR5cGU7CgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPGNhc3NlcnQ+CgoKLy9qdXN0IHRvIHBvcHVsYXRlIHdpdGggc29tZSB0eXBlcwpzdHJ1Y3QgU3RyaW5nOwpzdHJ1Y3QgQ29uZGl0aW9uOwpzdHJ1Y3QgT3BpbmlvbjsKCmludCBtYWluKCkKewoJdXNpbmcgTXlMaXN0ID0gdHlwZV9saXN0PGludCwgY2hhciwgYm9vbD47Cgl1c2luZyBGaXJzdCA9IHR5cGVfbGlzdF9leHRyYWN0X3Q8MCwgTXlMaXN0PjsKCXN0YXRpY19hc3NlcnQoc3RkOjppc19zYW1lPEZpcnN0LCBpbnQ+Ojp2YWx1ZSwgIiEiKTsKCgl1c2luZyBTZWNvbmRMaXN0ID0gdHlwZV9saXN0PFN0cmluZywgQ29uZGl0aW9uLCBPcGluaW9uPjsKCXVzaW5nIENvbmNhdCA9IHR5cGVfbGlzdF9jb25jYXRfdDxNeUxpc3QsIFNlY29uZExpc3Q+OwoJc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8dHlwZV9saXN0PGludCwgY2hhciwgYm9vbCwgU3RyaW5nLCBDb25kaXRpb24sIE9waW5pb24+LCBDb25jYXQ+Ojp2YWx1ZSwgIiEiKTsKCgl1c2luZyBFeHBhbnNpb24gPSB0eXBlX2xpc3RfZXhwYW5kX3Q8TXlMaXN0PjsKCXN0YXRpY19hc3NlcnQoc3RkOjppc19zYW1lPHN0ZDo6dHVwbGU8aW50LCBjaGFyLCBib29sPiwgRXhwYW5zaW9uPjo6dmFsdWUsICIhIik7CgoJdXNpbmcgUGFydGlhbEV4cGFuc2lvbiA9IHR5cGVfbGlzdF9leHBhbmRfdDxNeUxpc3QsIDAsIDI+OyAvL2ludCwgYm9vbAoJc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8c3RkOjp0dXBsZTxpbnQsIGJvb2w+LCBQYXJ0aWFsRXhwYW5zaW9uPjo6dmFsdWUsICIhIik7CgoJY29uc3RleHByIHN0ZDo6c2l6ZV90IHN6ID0gZmlyc3RfaW5kZXhfaG9sZGVyPDIsIDMsIDQ+Ojp2YWx1ZTsKCXN0YXRpY19hc3NlcnQoc3ogPT0gMiwgIiEiKTsKCgl1c2luZyBTZXEgPSBzdGQ6OmluZGV4X3NlcXVlbmNlPDIsIDMsIDQ+OwoJdXNpbmcgUmV2ZXJzZWRTZXEgPSByZXZlcnNlX2luZGV4X2ludGVydmFsPFNlcT46OnR5cGU7CglzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfc2FtZTxSZXZlcnNlZFNlcSwgc3RkOjppbmRleF9zZXF1ZW5jZTw0LCAzLCAyPiA+Ojp2YWx1ZSwgIiEiKTsKCgl1c2luZyBSZXYgPSB0eXBlX2xpc3RfcmV2ZXJzZV90PE15TGlzdD47CglzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfc2FtZTx0eXBlX2xpc3Q8Ym9vbCwgY2hhciwgaW50PiwgUmV2Pjo6dmFsdWUsICIhIik7CgoJCn0=