#include <iostream>
#include <type_traits>
// Helper template; needs no definition since we never instantiate it.
template <typename...> struct pack;
// Helper to allow us to obtain the last type from a pack.
template <typename> struct last_type_in_pack;
template <typename T>
struct last_type_in_pack<pack<T>>
{
typedef T type;
};
template <typename First, typename... Types>
struct last_type_in_pack<pack<First, Types...>>
: public last_type_in_pack<pack<Types...>> { };
// We need another helper to allow us to "peel off" the last type from a pack,
// turning pack<A, B, C> into pack<A, B> for example.
template <typename, typename> struct remove_last_type_from_pack_impl;
template <typename... Types, typename LastType>
struct remove_last_type_from_pack_impl<pack<Types...>, pack<LastType>>
{
typedef pack<Types...> type;
};
template <typename... TS1, typename T2, typename... TS2>
struct remove_last_type_from_pack_impl<pack<TS1...>, pack<T2, TS2...>>
: public remove_last_type_from_pack_impl<pack<TS1..., T2>, pack<TS2...>> { };
template <typename>
struct remove_last_type_from_pack;
template <typename... Types>
struct remove_last_type_from_pack<pack<Types...>>
: public remove_last_type_from_pack_impl<pack<>, pack<Types...>> { };
// Leave this undefined. It will cause invalid instantiations to fail since it's an
// incomplete type. All of our intended instantiations will be covered by partial
// specializations below.
template <typename...> struct Object;
// Partial specialization allowing "double-ended" packs, and requiring at least one
// parent type and one child type. (FirstParent exists solely to enforce that there
// is at least one parent type.)
template <typename FirstParent, typename... ParentTypes,
typename T,
typename FirstChild, typename... ChildTypes>
struct Object<pack<FirstParent, ParentTypes...>, T, pack<FirstChild, ChildTypes...>>
{
// We'll shift the packs around T to define our child and parent types:
typedef Object<pack<FirstParent, ParentTypes..., T>,
FirstChild,
pack<ChildTypes...>> child_type;
typedef Object<
typename remove_last_type_from_pack<pack<FirstParent, ParentTypes...>>::type,
typename last_type_in_pack<pack<FirstParent, ParentTypes...>>::type,
pack<T, FirstChild, ChildTypes...>> parent_type;
T item;
child_type * child;
parent_type * parent;
};
// Now we need specializations for parent-less and child-less.
// Parent-less:
template <typename T, typename FirstChild, typename... ChildTypes>
struct Object<pack<>, T, pack<FirstChild, ChildTypes...>>
{
typedef Object<pack<T>, FirstChild, pack<ChildTypes...>> child_type;
T item;
child_type * child;
};
// Child-less. As before, FirstParent just ensures that we have at least one parent
// type.
template <typename FirstParent, typename... ParentTypes, typename T>
struct Object<pack<FirstParent, ParentTypes...>, T, pack<>>
{
typedef Object<
typename remove_last_type_from_pack<pack<FirstParent, ParentTypes...>>::type,
typename last_type_in_pack<pack<FirstParent, ParentTypes...>>::type,
pack<T>> parent_type;
T item;
parent_type * parent;
};
// Note that Object<pack<>, T, pack<>> can't be instantiated since no specialization
// matches it, and the base template isn't defined. This type doesn't really make
// much sense, IMO, but you can specialize Object for it if you want:
//
// template <typename T>
// struct Object<pack<>, T, pack<>> { T item; };
template <typename Arg, typename... Rest>
using ObjectWithNoParent = Object<pack<>, Arg, pack<Rest...>>;
int main() {
Object<pack<>, int, pack<double, char, float, long>> a;
Object<pack<int>, double, pack<char, float, long>> b;
Object<pack<int, double>, char, pack<float, long>> c;
Object<pack<int, double, char>, float, pack<long>> d;
Object<pack<int, double, char, float>, long, pack<>> e;
static_assert(std::is_same<
typename Object<pack<int, double>, char, pack<float, long>>::parent_type,
Object<pack<int>, double, pack<char, float, long>>
>::value, "parent types match");
static_assert(std::is_same<
typename Object<pack<int, double>, char, pack<float, long>>::child_type,
Object<pack<int, double, char>, float, pack<long>>
>::value, "child types match");
// your code goes here
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgogICAgLy8gSGVscGVyIHRlbXBsYXRlOyBuZWVkcyBubyBkZWZpbml0aW9uIHNpbmNlIHdlIG5ldmVyIGluc3RhbnRpYXRlIGl0LgogICAgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBzdHJ1Y3QgcGFjazsKCiAgICAvLyBIZWxwZXIgdG8gYWxsb3cgdXMgdG8gb2J0YWluIHRoZSBsYXN0IHR5cGUgZnJvbSBhIHBhY2suCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWU+IHN0cnVjdCBsYXN0X3R5cGVfaW5fcGFjazsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIHN0cnVjdCBsYXN0X3R5cGVfaW5fcGFjazxwYWNrPFQ+PgogICAgewogICAgICAgIHR5cGVkZWYgVCB0eXBlOwogICAgfTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lLi4uIFR5cGVzPgogICAgc3RydWN0IGxhc3RfdHlwZV9pbl9wYWNrPHBhY2s8Rmlyc3QsIFR5cGVzLi4uPj4KICAgICAgICA6IHB1YmxpYyBsYXN0X3R5cGVfaW5fcGFjazxwYWNrPFR5cGVzLi4uPj4geyB9OwoKICAgIC8vIFdlIG5lZWQgYW5vdGhlciBoZWxwZXIgdG8gYWxsb3cgdXMgdG8gInBlZWwgb2ZmIiB0aGUgbGFzdCB0eXBlIGZyb20gYSBwYWNrLAogICAgLy8gdHVybmluZyBwYWNrPEEsIEIsIEM+IGludG8gcGFjazxBLCBCPiBmb3IgZXhhbXBsZS4KICAgIHRlbXBsYXRlIDx0eXBlbmFtZSwgdHlwZW5hbWU+IHN0cnVjdCByZW1vdmVfbGFzdF90eXBlX2Zyb21fcGFja19pbXBsOwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUeXBlcywgdHlwZW5hbWUgTGFzdFR5cGU+CiAgICBzdHJ1Y3QgcmVtb3ZlX2xhc3RfdHlwZV9mcm9tX3BhY2tfaW1wbDxwYWNrPFR5cGVzLi4uPiwgcGFjazxMYXN0VHlwZT4+CiAgICB7CiAgICAgICAgdHlwZWRlZiBwYWNrPFR5cGVzLi4uPiB0eXBlOwogICAgfTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gVFMxLCB0eXBlbmFtZSBUMiwgdHlwZW5hbWUuLi4gVFMyPgogICAgc3RydWN0IHJlbW92ZV9sYXN0X3R5cGVfZnJvbV9wYWNrX2ltcGw8cGFjazxUUzEuLi4+LCBwYWNrPFQyLCBUUzIuLi4+PgogICAgICAgIDogcHVibGljIHJlbW92ZV9sYXN0X3R5cGVfZnJvbV9wYWNrX2ltcGw8cGFjazxUUzEuLi4sIFQyPiwgcGFjazxUUzIuLi4+PiB7IH07CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lPgogICAgc3RydWN0IHJlbW92ZV9sYXN0X3R5cGVfZnJvbV9wYWNrOwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUeXBlcz4KICAgIHN0cnVjdCByZW1vdmVfbGFzdF90eXBlX2Zyb21fcGFjazxwYWNrPFR5cGVzLi4uPj4KICAgICAgICA6IHB1YmxpYyByZW1vdmVfbGFzdF90eXBlX2Zyb21fcGFja19pbXBsPHBhY2s8PiwgcGFjazxUeXBlcy4uLj4+IHsgfTsKCiAgICAvLyBMZWF2ZSB0aGlzIHVuZGVmaW5lZC4gIEl0IHdpbGwgY2F1c2UgaW52YWxpZCBpbnN0YW50aWF0aW9ucyB0byBmYWlsIHNpbmNlIGl0J3MgYW4KICAgIC8vIGluY29tcGxldGUgdHlwZS4gIEFsbCBvZiBvdXIgaW50ZW5kZWQgaW5zdGFudGlhdGlvbnMgd2lsbCBiZSBjb3ZlcmVkIGJ5IHBhcnRpYWwKICAgIC8vIHNwZWNpYWxpemF0aW9ucyBiZWxvdy4KICAgIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gc3RydWN0IE9iamVjdDsKCiAgICAvLyBQYXJ0aWFsIHNwZWNpYWxpemF0aW9uIGFsbG93aW5nICJkb3VibGUtZW5kZWQiIHBhY2tzLCBhbmQgcmVxdWlyaW5nIGF0IGxlYXN0IG9uZQogICAgLy8gcGFyZW50IHR5cGUgYW5kIG9uZSBjaGlsZCB0eXBlLiAgKEZpcnN0UGFyZW50IGV4aXN0cyBzb2xlbHkgdG8gZW5mb3JjZSB0aGF0IHRoZXJlCiAgICAvLyBpcyBhdCBsZWFzdCBvbmUgcGFyZW50IHR5cGUuKQogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEZpcnN0UGFyZW50LCB0eXBlbmFtZS4uLiBQYXJlbnRUeXBlcywKICAgICAgICAgICAgICB0eXBlbmFtZSBULAogICAgICAgICAgICAgIHR5cGVuYW1lIEZpcnN0Q2hpbGQsIHR5cGVuYW1lLi4uIENoaWxkVHlwZXM+CiAgICBzdHJ1Y3QgT2JqZWN0PHBhY2s8Rmlyc3RQYXJlbnQsIFBhcmVudFR5cGVzLi4uPiwgVCwgcGFjazxGaXJzdENoaWxkLCBDaGlsZFR5cGVzLi4uPj4KICAgIHsKICAgICAgICAvLyBXZSdsbCBzaGlmdCB0aGUgcGFja3MgYXJvdW5kIFQgdG8gZGVmaW5lIG91ciBjaGlsZCBhbmQgcGFyZW50IHR5cGVzOgogICAgICAgIHR5cGVkZWYgT2JqZWN0PHBhY2s8Rmlyc3RQYXJlbnQsIFBhcmVudFR5cGVzLi4uLCBUPiwKICAgICAgICAgICAgICAgICAgICAgICBGaXJzdENoaWxkLAogICAgICAgICAgICAgICAgICAgICAgIHBhY2s8Q2hpbGRUeXBlcy4uLj4+IGNoaWxkX3R5cGU7CgogICAgICAgIHR5cGVkZWYgT2JqZWN0PAogICAgICAgICAgICB0eXBlbmFtZSByZW1vdmVfbGFzdF90eXBlX2Zyb21fcGFjazxwYWNrPEZpcnN0UGFyZW50LCBQYXJlbnRUeXBlcy4uLj4+Ojp0eXBlLAogICAgICAgICAgICB0eXBlbmFtZSBsYXN0X3R5cGVfaW5fcGFjazxwYWNrPEZpcnN0UGFyZW50LCBQYXJlbnRUeXBlcy4uLj4+Ojp0eXBlLAogICAgICAgICAgICBwYWNrPFQsIEZpcnN0Q2hpbGQsIENoaWxkVHlwZXMuLi4+PiBwYXJlbnRfdHlwZTsKCiAgICAgICAgVCBpdGVtOwogICAgICAgIGNoaWxkX3R5cGUgKiBjaGlsZDsKICAgICAgICBwYXJlbnRfdHlwZSAqIHBhcmVudDsKICAgIH07CgogICAgLy8gTm93IHdlIG5lZWQgc3BlY2lhbGl6YXRpb25zIGZvciBwYXJlbnQtbGVzcyBhbmQgY2hpbGQtbGVzcy4KCiAgICAvLyBQYXJlbnQtbGVzczoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBGaXJzdENoaWxkLCB0eXBlbmFtZS4uLiBDaGlsZFR5cGVzPgogICAgc3RydWN0IE9iamVjdDxwYWNrPD4sIFQsIHBhY2s8Rmlyc3RDaGlsZCwgQ2hpbGRUeXBlcy4uLj4+CiAgICB7CiAgICAgICAgdHlwZWRlZiBPYmplY3Q8cGFjazxUPiwgRmlyc3RDaGlsZCwgcGFjazxDaGlsZFR5cGVzLi4uPj4gY2hpbGRfdHlwZTsKCiAgICAgICAgVCBpdGVtOwogICAgICAgIGNoaWxkX3R5cGUgKiBjaGlsZDsKICAgIH07CgogICAgLy8gQ2hpbGQtbGVzcy4gIEFzIGJlZm9yZSwgRmlyc3RQYXJlbnQganVzdCBlbnN1cmVzIHRoYXQgd2UgaGF2ZSBhdCBsZWFzdCBvbmUgcGFyZW50CiAgICAvLyB0eXBlLgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEZpcnN0UGFyZW50LCB0eXBlbmFtZS4uLiBQYXJlbnRUeXBlcywgdHlwZW5hbWUgVD4KICAgIHN0cnVjdCBPYmplY3Q8cGFjazxGaXJzdFBhcmVudCwgUGFyZW50VHlwZXMuLi4+LCBULCBwYWNrPD4+CiAgICB7CiAgICAgICAgdHlwZWRlZiBPYmplY3Q8CiAgICAgICAgICAgIHR5cGVuYW1lIHJlbW92ZV9sYXN0X3R5cGVfZnJvbV9wYWNrPHBhY2s8Rmlyc3RQYXJlbnQsIFBhcmVudFR5cGVzLi4uPj46OnR5cGUsCiAgICAgICAgICAgIHR5cGVuYW1lIGxhc3RfdHlwZV9pbl9wYWNrPHBhY2s8Rmlyc3RQYXJlbnQsIFBhcmVudFR5cGVzLi4uPj46OnR5cGUsCiAgICAgICAgICAgIHBhY2s8VD4+IHBhcmVudF90eXBlOwoKICAgICAgICBUIGl0ZW07CiAgICAgICAgcGFyZW50X3R5cGUgKiBwYXJlbnQ7CiAgICB9OwoKICAgIC8vIE5vdGUgdGhhdCBPYmplY3Q8cGFjazw+LCBULCBwYWNrPD4+IGNhbid0IGJlIGluc3RhbnRpYXRlZCBzaW5jZSBubyBzcGVjaWFsaXphdGlvbgogICAgLy8gbWF0Y2hlcyBpdCwgYW5kIHRoZSBiYXNlIHRlbXBsYXRlIGlzbid0IGRlZmluZWQuIFRoaXMgdHlwZSBkb2Vzbid0IHJlYWxseSBtYWtlCiAgICAvLyBtdWNoIHNlbnNlLCBJTU8sIGJ1dCB5b3UgY2FuIHNwZWNpYWxpemUgT2JqZWN0IGZvciBpdCBpZiB5b3Ugd2FudDoKICAgIC8vCiAgICAvLyB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIC8vIHN0cnVjdCBPYmplY3Q8cGFjazw+LCBULCBwYWNrPD4+IHsgVCBpdGVtOyB9OwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBBcmcsIHR5cGVuYW1lLi4uIFJlc3Q+CiAgICB1c2luZyBPYmplY3RXaXRoTm9QYXJlbnQgPSBPYmplY3Q8cGFjazw+LCBBcmcsIHBhY2s8UmVzdC4uLj4+OwoKaW50IG1haW4oKSB7CglPYmplY3Q8cGFjazw+LCBpbnQsIHBhY2s8ZG91YmxlLCBjaGFyLCBmbG9hdCwgbG9uZz4+IGE7CglPYmplY3Q8cGFjazxpbnQ+LCBkb3VibGUsIHBhY2s8Y2hhciwgZmxvYXQsIGxvbmc+PiBiOwoJT2JqZWN0PHBhY2s8aW50LCBkb3VibGU+LCBjaGFyLCBwYWNrPGZsb2F0LCBsb25nPj4gYzsKCU9iamVjdDxwYWNrPGludCwgZG91YmxlLCBjaGFyPiwgZmxvYXQsIHBhY2s8bG9uZz4+IGQ7CglPYmplY3Q8cGFjazxpbnQsIGRvdWJsZSwgY2hhciwgZmxvYXQ+LCBsb25nLCBwYWNrPD4+IGU7CgkKCXN0YXRpY19hc3NlcnQoc3RkOjppc19zYW1lPAoJICAgIHR5cGVuYW1lIE9iamVjdDxwYWNrPGludCwgZG91YmxlPiwgY2hhciwgcGFjazxmbG9hdCwgbG9uZz4+OjpwYXJlbnRfdHlwZSwKCSAgICBPYmplY3Q8cGFjazxpbnQ+LCBkb3VibGUsIHBhY2s8Y2hhciwgZmxvYXQsIGxvbmc+PgoJPjo6dmFsdWUsICJwYXJlbnQgdHlwZXMgbWF0Y2giKTsKCQoJc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8CgkgICAgdHlwZW5hbWUgT2JqZWN0PHBhY2s8aW50LCBkb3VibGU+LCBjaGFyLCBwYWNrPGZsb2F0LCBsb25nPj46OmNoaWxkX3R5cGUsCgkgICAgT2JqZWN0PHBhY2s8aW50LCBkb3VibGUsIGNoYXI+LCBmbG9hdCwgcGFjazxsb25nPj4KCT46OnZhbHVlLCAiY2hpbGQgdHlwZXMgbWF0Y2giKTsKCQoJLy8geW91ciBjb2RlIGdvZXMgaGVyZQoJcmV0dXJuIDA7Cn0=