#include <tuple>
#include <type_traits>
template < typename T>
struct Identity { using type = T; } ;
// ExistsInPack
template < typename T, typename Pack> struct ExistsInPack;
template < typename T, template < typename ...> class P>
struct ExistsInPack< T, P<>> : std:: false_type { } ;
template < typename T, template < typename ...> class P, typename First, typename ... Rest >
struct ExistsInPack< T, P< First, Rest...>> : ExistsInPack< T, P< Rest...>> { } ;
template < typename T, template < typename ...> class P, typename ... Rest >
struct ExistsInPack< T, P< T, Rest...>> : std:: true_type { } ;
// IsEmpty
template < typename T>
struct IsEmpty : std:: false_type { } ;
template < template < typename ...> class P>
struct IsEmpty< P<>> : std:: true_type { } ;
// Union of packs.
template < typename , typename , typename > struct UnionHelper;
template < template < typename ...> class P, typename ... Types , typename ... Accumulated >
struct UnionHelper< P< Types...> , P<> , P< Accumulated...>> {
using type = P< Accumulated...> ;
} ;
template < template < typename ...> class P, typename First, typename ... Rest , typename ... Types , typename ... Accumulated >
struct UnionHelper< P< Types...> , P< First, Rest...> , P< Accumulated...>> : std:: conditional_t < ExistsInPack< First, P< Types...>> :: value ,
UnionHelper< P< Types...> , P< Rest...> , P< Accumulated...>> ,
UnionHelper< P< Types...> , P< Rest...> , P< Accumulated..., First>>
> { } ;
template < typename ...> struct Union;
template <>
struct Union<> { using type = void ; } ;
template < typename Pack>
struct Union< Pack> : Identity< Pack> { } ;
template < typename Pack1, typename Pack2>
struct Union< Pack1, Pack2> : UnionHelper< Pack1, Pack2, Pack1> { } ;
template < typename Pack1, typename Pack2, typename ... Packs >
struct Union< Pack1, Pack2, Packs...> : Union< typename Union< Pack1, Pack2> :: type , Packs...> { } ;
// CombineLinks
template < template < typename > class Link, template < typename ...> class Combine, typename Pack> struct CombineLinks;
template < template < typename > class Link, template < typename ...> class Combine, template < typename ...> class P, typename ... Ts >
struct CombineLinks< Link, Combine, P< Ts...>> : Combine< Link< Ts> ...> { } ; // Right here! Link<Ts> must remove any member of that pack that is already in the union. This idea MIGHT work.
template < template < typename > class Link, template < typename ...> class Combine, template < typename ...> class P>
struct CombineLinks< Link, Combine, P<>> : Identity < std:: tuple <>> { } ;
// Network<T, Link, Combine> is the "combining" (specified by Combine) of all the links of T (specified by Link), and their links, and their links, etc... until there are no more links.
template < template < typename > class Link, template < typename ...> class Combine, typename ...> struct NetworkHelper;
template < template < typename > class Link, template < typename ...> class Combine, typename T, typename First, typename ... Rest >
using NetworkHelperAlias = std:: conditional_t < IsEmpty< T> :: value , Combine< First, Rest...> , NetworkHelper< Link, Combine, T, First, Rest...> > ;
template < template < typename > class Link, template < typename ...> class Combine, typename First, typename ... Rest >
struct NetworkHelper< Link, Combine, First, Rest...> : NetworkHelperAlias< Link, Combine, typename CombineLinks< Link, Combine, First> :: type , First, Rest...> { } ;
template < typename T, template < typename > class Link, template < typename ...> class Combine>
using Network = NetworkHelper< Link, Combine, std:: tuple < T>> ;
// Detecting if the member type T::links exists in class T.
template < typename T>
using void_t = void ;
template < typename T, typename = void >
struct has_links_member : std:: false_type { } ;
template < typename T>
struct has_links_member< T, void_t< typename T:: links >> : std:: true_type { } ;
// LinkedTypes<T> is T::links if such a member type exists in T.
template < typename T, bool HasLinksMember>
struct LinkedTypesHelper : Identity < typename T:: links > { } ;
template < typename T>
struct LinkedTypesHelper< T, false > : Identity < std:: tuple <>> { } ;
template < typename T>
using LinkedTypes = typename LinkedTypesHelper< T, has_links_member< T> :: value > :: type ;
// Template alias of Network using Link = LinkedTypes and Combine = Union.
template < typename T>
using AllLinksFrom = typename Network< T, LinkedTypes, Union> :: type ;
// Testing
#include <iostream>
struct A { } ;
struct B { using links = std:: tuple < A> ; } ;
struct C { using links = std:: tuple < A,B> ; } ;
struct D { using links = std:: tuple < C> ; } ;
struct E { using links = std:: tuple < D> ; } ;
struct F { using links = std:: tuple < D> ; } ;
struct G { using links = std:: tuple < D> ; } ;
struct H { using links = std:: tuple < E,F,G> ; } ;
struct Foo;
struct Bar { using links = std:: tuple < Foo> ; } ;
struct Foo { using links = std:: tuple < Bar> ; } ;
int main( ) {
std:: cout << std:: boolalpha << std:: is_same <
AllLinksFrom< H> ,
std:: tuple < A,B,C,D,E,F,G,H>
> :: value << '\n ' ; // true
// std::cout << std::is_same<
// AllLinksFrom<Foo>,
// std::tuple<Bar, Foo>
// >::value << '\n'; // Infinite recursion.
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IElkZW50aXR5IHsgdXNpbmcgdHlwZSA9IFQ7IH07CgovLyBFeGlzdHNJblBhY2sKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFBhY2s+IHN0cnVjdCBFeGlzdHNJblBhY2s7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQPgpzdHJ1Y3QgRXhpc3RzSW5QYWNrPFQsIFA8Pj4gOiBzdGQ6OmZhbHNlX3R5cGUge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQLCB0eXBlbmFtZSBGaXJzdCwgdHlwZW5hbWUuLi4gUmVzdD4Kc3RydWN0IEV4aXN0c0luUGFjazxULCBQPEZpcnN0LCBSZXN0Li4uPj4gOiBFeGlzdHNJblBhY2s8VCwgUDxSZXN0Li4uPj4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQLCB0eXBlbmFtZS4uLiBSZXN0PgpzdHJ1Y3QgRXhpc3RzSW5QYWNrPFQsIFA8VCwgUmVzdC4uLj4+IDogc3RkOjp0cnVlX3R5cGUge307CgovLyBJc0VtcHR5CnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpzdHJ1Y3QgSXNFbXB0eSA6IHN0ZDo6ZmFsc2VfdHlwZSB7fTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFA+CnN0cnVjdCBJc0VtcHR5PFA8Pj4gOiBzdGQ6OnRydWVfdHlwZSB7fTsKCi8vIFVuaW9uIG9mIHBhY2tzLgp0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lLCB0eXBlbmFtZT4gc3RydWN0IFVuaW9uSGVscGVyOwoKdGVtcGxhdGUgPHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUCwgdHlwZW5hbWUuLi4gVHlwZXMsIHR5cGVuYW1lLi4uIEFjY3VtdWxhdGVkPgpzdHJ1Y3QgVW5pb25IZWxwZXI8UDxUeXBlcy4uLj4sIFA8PiwgUDxBY2N1bXVsYXRlZC4uLj4+IHsKCXVzaW5nIHR5cGUgPSBQPEFjY3VtdWxhdGVkLi4uPjsKfTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFAsIHR5cGVuYW1lIEZpcnN0LCB0eXBlbmFtZS4uLiBSZXN0LCB0eXBlbmFtZS4uLiBUeXBlcywgdHlwZW5hbWUuLi4gQWNjdW11bGF0ZWQ+CnN0cnVjdCBVbmlvbkhlbHBlcjxQPFR5cGVzLi4uPiwgUDxGaXJzdCwgUmVzdC4uLj4sIFA8QWNjdW11bGF0ZWQuLi4+PiA6IHN0ZDo6Y29uZGl0aW9uYWxfdDxFeGlzdHNJblBhY2s8Rmlyc3QsIFA8VHlwZXMuLi4+Pjo6dmFsdWUsCgkJVW5pb25IZWxwZXI8UDxUeXBlcy4uLj4sIFA8UmVzdC4uLj4sIFA8QWNjdW11bGF0ZWQuLi4+PiwKCQlVbmlvbkhlbHBlcjxQPFR5cGVzLi4uPiwgUDxSZXN0Li4uPiwgUDxBY2N1bXVsYXRlZC4uLiwgRmlyc3Q+PgoJPiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gc3RydWN0IFVuaW9uOwoKdGVtcGxhdGUgPD4Kc3RydWN0IFVuaW9uPD4geyB1c2luZyB0eXBlID0gdm9pZDsgfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBQYWNrPgpzdHJ1Y3QgVW5pb248UGFjaz4gOiBJZGVudGl0eTxQYWNrPiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBQYWNrMSwgdHlwZW5hbWUgUGFjazI+CnN0cnVjdCBVbmlvbjxQYWNrMSwgUGFjazI+IDogVW5pb25IZWxwZXI8UGFjazEsIFBhY2syLCBQYWNrMT4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUGFjazEsIHR5cGVuYW1lIFBhY2syLCB0eXBlbmFtZS4uLiBQYWNrcz4Kc3RydWN0IFVuaW9uPFBhY2sxLCBQYWNrMiwgUGFja3MuLi4+IDogVW5pb248dHlwZW5hbWUgVW5pb248UGFjazEsIFBhY2syPjo6dHlwZSwgUGFja3MuLi4+IHt9OwoKLy8gQ29tYmluZUxpbmtzCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWU+IGNsYXNzIExpbmssIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgQ29tYmluZSwgdHlwZW5hbWUgUGFjaz4gc3RydWN0IENvbWJpbmVMaW5rczsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWU+IGNsYXNzIExpbmssIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgQ29tYmluZSwgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQLCB0eXBlbmFtZS4uLiBUcz4Kc3RydWN0IENvbWJpbmVMaW5rczxMaW5rLCBDb21iaW5lLCBQPFRzLi4uPj4gOiBDb21iaW5lPExpbms8VHM+Li4uPiB7fTsgIC8vIFJpZ2h0IGhlcmUhICBMaW5rPFRzPiBtdXN0IHJlbW92ZSBhbnkgbWVtYmVyIG9mIHRoYXQgcGFjayB0aGF0IGlzIGFscmVhZHkgaW4gdGhlIHVuaW9uLiAgVGhpcyBpZGVhIE1JR0hUIHdvcmsuCgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBMaW5rLCB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIENvbWJpbmUsIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUD4Kc3RydWN0IENvbWJpbmVMaW5rczxMaW5rLCBDb21iaW5lLCBQPD4+IDogSWRlbnRpdHkgPHN0ZDo6dHVwbGU8Pj4ge307CgovLyBOZXR3b3JrPFQsIExpbmssIENvbWJpbmU+IGlzIHRoZSAiY29tYmluaW5nIiAoc3BlY2lmaWVkIGJ5IENvbWJpbmUpIG9mIGFsbCB0aGUgbGlua3Mgb2YgVCAoc3BlY2lmaWVkIGJ5IExpbmspLCBhbmQgdGhlaXIgbGlua3MsIGFuZCB0aGVpciBsaW5rcywgZXRjLi4uIHVudGlsIHRoZXJlIGFyZSBubyBtb3JlIGxpbmtzLgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBMaW5rLCB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIENvbWJpbmUsIHR5cGVuYW1lLi4uPiBzdHJ1Y3QgTmV0d29ya0hlbHBlcjsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWU+IGNsYXNzIExpbmssIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgQ29tYmluZSwgdHlwZW5hbWUgVCwgdHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lLi4uIFJlc3Q+CnVzaW5nIE5ldHdvcmtIZWxwZXJBbGlhcyA9IHN0ZDo6Y29uZGl0aW9uYWxfdDwgSXNFbXB0eTxUPjo6dmFsdWUsICBDb21iaW5lPEZpcnN0LCBSZXN0Li4uPiwgIE5ldHdvcmtIZWxwZXI8TGluaywgQ29tYmluZSwgVCwgRmlyc3QsIFJlc3QuLi4+ID47Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBMaW5rLCB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIENvbWJpbmUsIHR5cGVuYW1lIEZpcnN0LCB0eXBlbmFtZS4uLiBSZXN0PgpzdHJ1Y3QgTmV0d29ya0hlbHBlcjxMaW5rLCBDb21iaW5lLCBGaXJzdCwgUmVzdC4uLj4gOiBOZXR3b3JrSGVscGVyQWxpYXM8TGluaywgQ29tYmluZSwgdHlwZW5hbWUgQ29tYmluZUxpbmtzPExpbmssIENvbWJpbmUsIEZpcnN0Pjo6dHlwZSwgRmlyc3QsIFJlc3QuLi4+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDx0eXBlbmFtZT4gY2xhc3MgTGluaywgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBDb21iaW5lPgp1c2luZyBOZXR3b3JrID0gTmV0d29ya0hlbHBlcjxMaW5rLCBDb21iaW5lLCBzdGQ6OnR1cGxlPFQ+PjsKCi8vIERldGVjdGluZyBpZiB0aGUgbWVtYmVyIHR5cGUgVDo6bGlua3MgZXhpc3RzIGluIGNsYXNzIFQuCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgp1c2luZyB2b2lkX3QgPSB2b2lkOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lID0gdm9pZD4Kc3RydWN0IGhhc19saW5rc19tZW1iZXIgOiBzdGQ6OmZhbHNlX3R5cGUge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IGhhc19saW5rc19tZW1iZXI8VCwgdm9pZF90PHR5cGVuYW1lIFQ6OmxpbmtzPj4gOiBzdGQ6OnRydWVfdHlwZSB7fTsKCi8vIExpbmtlZFR5cGVzPFQ+IGlzIFQ6OmxpbmtzIGlmIHN1Y2ggYSBtZW1iZXIgdHlwZSBleGlzdHMgaW4gVC4KdGVtcGxhdGUgPHR5cGVuYW1lIFQsIGJvb2wgSGFzTGlua3NNZW1iZXI+CnN0cnVjdCBMaW5rZWRUeXBlc0hlbHBlciA6IElkZW50aXR5IDx0eXBlbmFtZSBUOjpsaW5rcz4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IExpbmtlZFR5cGVzSGVscGVyPFQsIGZhbHNlPiA6IElkZW50aXR5IDxzdGQ6OnR1cGxlPD4+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnVzaW5nIExpbmtlZFR5cGVzID0gdHlwZW5hbWUgTGlua2VkVHlwZXNIZWxwZXI8VCwgaGFzX2xpbmtzX21lbWJlcjxUPjo6dmFsdWU+Ojp0eXBlOwoKLy8gVGVtcGxhdGUgYWxpYXMgb2YgTmV0d29yayB1c2luZyBMaW5rID0gTGlua2VkVHlwZXMgYW5kIENvbWJpbmUgPSBVbmlvbi4KdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnVzaW5nIEFsbExpbmtzRnJvbSA9IHR5cGVuYW1lIE5ldHdvcms8VCwgTGlua2VkVHlwZXMsIFVuaW9uPjo6dHlwZTsKCi8vIFRlc3RpbmcKI2luY2x1ZGUgPGlvc3RyZWFtPgoKc3RydWN0IEEge307CnN0cnVjdCBCIHsgdXNpbmcgbGlua3MgPSBzdGQ6OnR1cGxlPEE+OyB9OwpzdHJ1Y3QgQyB7IHVzaW5nIGxpbmtzID0gc3RkOjp0dXBsZTxBLEI+OyB9OwpzdHJ1Y3QgRCB7IHVzaW5nIGxpbmtzID0gc3RkOjp0dXBsZTxDPjsgfTsKc3RydWN0IEUgeyB1c2luZyBsaW5rcyA9IHN0ZDo6dHVwbGU8RD47IH07CnN0cnVjdCBGIHsgdXNpbmcgbGlua3MgPSBzdGQ6OnR1cGxlPEQ+OyB9OwpzdHJ1Y3QgRyB7IHVzaW5nIGxpbmtzID0gc3RkOjp0dXBsZTxEPjsgfTsKc3RydWN0IEggeyB1c2luZyBsaW5rcyA9IHN0ZDo6dHVwbGU8RSxGLEc+OyB9OwoKc3RydWN0IEZvbzsKc3RydWN0IEJhciB7IHVzaW5nIGxpbmtzID0gc3RkOjp0dXBsZTxGb28+OyB9OwpzdHJ1Y3QgRm9vIHsgdXNpbmcgbGlua3MgPSBzdGQ6OnR1cGxlPEJhcj47IH07CgppbnQgbWFpbigpIHsKCXN0ZDo6Y291dCA8PCBzdGQ6OmJvb2xhbHBoYSA8PCBzdGQ6OmlzX3NhbWU8CgkJQWxsTGlua3NGcm9tPEg+LAoJCXN0ZDo6dHVwbGU8QSxCLEMsRCxFLEYsRyxIPgoJPjo6dmFsdWUgPDwgJ1xuJzsgIC8vIHRydWUKCi8vCXN0ZDo6Y291dCA8PCBzdGQ6OmlzX3NhbWU8Ci8vCQlBbGxMaW5rc0Zyb208Rm9vPiwKLy8JCXN0ZDo6dHVwbGU8QmFyLCBGb28+Ci8vCT46OnZhbHVlIDw8ICdcbic7ICAvLyBJbmZpbml0ZSByZWN1cnNpb24uCn0=