#include <iostream>
#include <typeinfo>
#include <type_traits>
struct Grandma {};
struct Mom: Grandma {};
struct Daughter: Mom {};
struct Son: Mom {};
struct Grandchild: Son {};
struct Stranger {};
namespace detail
{
struct TypeIsNotPartOfTheHierarchy {};
template<typename T>
struct TypeWrapper
{
static_assert(!std::is_same<TypeIsNotPartOfTheHierarchy, T>::value,
"using types of different type hierarchies.");
using type = T;
};
template<typename StillCommonAncestor, typename TypeToCheck, typename... Ts>
struct IsCommonAncestor;
template<typename StillCommonAncestor, typename TypeToCheck>
struct IsCommonAncestor<StillCommonAncestor, TypeToCheck>
{
static constexpr bool value = StillCommonAncestor::value;
};
template<typename StillCommonAncestor, typename TypeToCheck, typename T1, typename... Ts>
struct IsCommonAncestor<StillCommonAncestor, TypeToCheck, T1, Ts...>:
IsCommonAncestor
<
std::integral_constant
<
bool,
std::conditional
<
std::is_base_of<TypeToCheck, T1>::value,
std::true_type,
std::false_type
>::type::value && StillCommonAncestor::value
>,
TypeToCheck,
Ts...
>
{};
template<typename Pack, typename... Ts>
struct LCA;
template<typename... PackParams, typename T1>
struct LCA<std::tuple<PackParams...>, T1>:
std::conditional
<
IsCommonAncestor<std::true_type, T1, PackParams...>::value,
TypeWrapper<T1>,
TypeWrapper<TypeIsNotPartOfTheHierarchy>
>::type
{};
template<typename... PackParams, typename T1, typename... Ts>
struct LCA<std::tuple<PackParams...>, T1, Ts...>:
std::conditional
<
IsCommonAncestor<std::true_type, T1, PackParams...>::value,
TypeWrapper<T1>,
LCA<std::tuple<PackParams...>, Ts...>
>::type
{};
}
template<typename... Ts>
struct LCA: detail::LCA<std::tuple<Ts...>, Ts...>
{};
int main()
{
std::cout << typeid(LCA<Son, Daughter, Mom, Grandchild, Grandma, Son, Son>::type).name() << std::endl;
std::cout << typeid(LCA<Son>::type).name() << std::endl;
std::cout << typeid(LCA<Grandma, Daughter, Son>::type).name() << std::endl;
// error because Daughter and Son are orphans in the list
// std::cout << typeid(LCA<Daughter, Son>::type).name() << std::endl;
// error because the Son and his Grandma are not related to Stranger.
// std::cout << typeid(LCA<Grandma, Stranger, Son>::type).name() << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZWluZm8+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KCnN0cnVjdCBHcmFuZG1hICAgICAgICAgICAgIHt9OwpzdHJ1Y3QgTW9tOiAgICAgICAgR3JhbmRtYSB7fTsKc3RydWN0IERhdWdodGVyOiAgIE1vbSAgICAge307CnN0cnVjdCBTb246ICAgICAgICBNb20gICAgIHt9OwpzdHJ1Y3QgR3JhbmRjaGlsZDogU29uICAgICB7fTsKCnN0cnVjdCBTdHJhbmdlciAgICAgICAgICAgIHt9OwoKbmFtZXNwYWNlIGRldGFpbAp7CgogICAgc3RydWN0IFR5cGVJc05vdFBhcnRPZlRoZUhpZXJhcmNoeSB7fTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPgogICAgc3RydWN0IFR5cGVXcmFwcGVyCiAgICB7CiAgICAgICAgc3RhdGljX2Fzc2VydCghc3RkOjppc19zYW1lPFR5cGVJc05vdFBhcnRPZlRoZUhpZXJhcmNoeSwgVD46OnZhbHVlLAogICAgICAgICAgICAidXNpbmcgdHlwZXMgb2YgZGlmZmVyZW50IHR5cGUgaGllcmFyY2hpZXMuIik7CgogICAgICAgIHVzaW5nIHR5cGUgPSBUOwogICAgfTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBTdGlsbENvbW1vbkFuY2VzdG9yLCB0eXBlbmFtZSBUeXBlVG9DaGVjaywgdHlwZW5hbWUuLi4gVHM+CiAgICBzdHJ1Y3QgSXNDb21tb25BbmNlc3RvcjsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBTdGlsbENvbW1vbkFuY2VzdG9yLCB0eXBlbmFtZSBUeXBlVG9DaGVjaz4KICAgIHN0cnVjdCBJc0NvbW1vbkFuY2VzdG9yPFN0aWxsQ29tbW9uQW5jZXN0b3IsIFR5cGVUb0NoZWNrPgogICAgewogICAgICAgIHN0YXRpYyBjb25zdGV4cHIgYm9vbCB2YWx1ZSA9IFN0aWxsQ29tbW9uQW5jZXN0b3I6OnZhbHVlOwogICAgfTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBTdGlsbENvbW1vbkFuY2VzdG9yLCB0eXBlbmFtZSBUeXBlVG9DaGVjaywgdHlwZW5hbWUgVDEsIHR5cGVuYW1lLi4uIFRzPgogICAgc3RydWN0IElzQ29tbW9uQW5jZXN0b3I8U3RpbGxDb21tb25BbmNlc3RvciwgVHlwZVRvQ2hlY2ssIFQxLCBUcy4uLj46CiAgICAgICAgSXNDb21tb25BbmNlc3RvcgogICAgICAgIDwKICAgICAgICAgICAgc3RkOjppbnRlZ3JhbF9jb25zdGFudAogICAgICAgICAgICA8CiAgICAgICAgICAgICAgICBib29sLAogICAgICAgICAgICAgICAgc3RkOjpjb25kaXRpb25hbAogICAgICAgICAgICAgICAgPAogICAgICAgICAgICAgICAgICAgIHN0ZDo6aXNfYmFzZV9vZjxUeXBlVG9DaGVjaywgVDE+Ojp2YWx1ZSwKICAgICAgICAgICAgICAgICAgICBzdGQ6OnRydWVfdHlwZSwKICAgICAgICAgICAgICAgICAgICBzdGQ6OmZhbHNlX3R5cGUKICAgICAgICAgICAgICAgID46OnR5cGU6OnZhbHVlICYmIFN0aWxsQ29tbW9uQW5jZXN0b3I6OnZhbHVlCiAgICAgICAgICAgID4sCiAgICAgICAgICAgIFR5cGVUb0NoZWNrLAogICAgICAgICAgICBUcy4uLgogICAgICAgID4KICAgIHt9OwoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFBhY2ssIHR5cGVuYW1lLi4uIFRzPgogICAgc3RydWN0IExDQTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBQYWNrUGFyYW1zLCB0eXBlbmFtZSBUMT4KICAgIHN0cnVjdCBMQ0E8c3RkOjp0dXBsZTxQYWNrUGFyYW1zLi4uPiwgVDE+OgogICAgICAgIHN0ZDo6Y29uZGl0aW9uYWwKICAgICAgICA8CiAgICAgICAgICAgIElzQ29tbW9uQW5jZXN0b3I8c3RkOjp0cnVlX3R5cGUsIFQxLCBQYWNrUGFyYW1zLi4uPjo6dmFsdWUsCiAgICAgICAgICAgIFR5cGVXcmFwcGVyPFQxPiwKICAgICAgICAgICAgVHlwZVdyYXBwZXI8VHlwZUlzTm90UGFydE9mVGhlSGllcmFyY2h5PgogICAgICAgID46OnR5cGUKICAgIHt9OwoKICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFBhY2tQYXJhbXMsIHR5cGVuYW1lIFQxLCB0eXBlbmFtZS4uLiBUcz4KICAgIHN0cnVjdCBMQ0E8c3RkOjp0dXBsZTxQYWNrUGFyYW1zLi4uPiwgVDEsIFRzLi4uPjoKICAgICAgICBzdGQ6OmNvbmRpdGlvbmFsCiAgICAgICAgPAogICAgICAgICAgICBJc0NvbW1vbkFuY2VzdG9yPHN0ZDo6dHJ1ZV90eXBlLCBUMSwgUGFja1BhcmFtcy4uLj46OnZhbHVlLAogICAgICAgICAgICBUeXBlV3JhcHBlcjxUMT4sCiAgICAgICAgICAgIExDQTxzdGQ6OnR1cGxlPFBhY2tQYXJhbXMuLi4+LCBUcy4uLj4KICAgICAgICA+Ojp0eXBlCiAgICB7fTsKCn0KCnRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3QgTENBOiBkZXRhaWw6OkxDQTxzdGQ6OnR1cGxlPFRzLi4uPiwgVHMuLi4+Cnt9OwoKaW50IG1haW4oKQp7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZWlkKExDQTxTb24sIERhdWdodGVyLCBNb20sIEdyYW5kY2hpbGQsIEdyYW5kbWEsIFNvbiwgU29uPjo6dHlwZSkubmFtZSgpIDw8IHN0ZDo6ZW5kbDsKICAgIHN0ZDo6Y291dCA8PCB0eXBlaWQoTENBPFNvbj46OnR5cGUpLm5hbWUoKSA8PCBzdGQ6OmVuZGw7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZWlkKExDQTxHcmFuZG1hLCBEYXVnaHRlciwgU29uPjo6dHlwZSkubmFtZSgpIDw8IHN0ZDo6ZW5kbDsKCiAgICAvLyBlcnJvciBiZWNhdXNlIERhdWdodGVyIGFuZCBTb24gYXJlIG9ycGhhbnMgaW4gdGhlIGxpc3QKICAgIC8vIHN0ZDo6Y291dCA8PCB0eXBlaWQoTENBPERhdWdodGVyLCBTb24+Ojp0eXBlKS5uYW1lKCkgPDwgc3RkOjplbmRsOwoKICAgIC8vIGVycm9yIGJlY2F1c2UgdGhlIFNvbiBhbmQgaGlzIEdyYW5kbWEgYXJlIG5vdCByZWxhdGVkIHRvIFN0cmFuZ2VyLgogICAgLy8gc3RkOjpjb3V0IDw8IHR5cGVpZChMQ0E8R3JhbmRtYSwgU3RyYW5nZXIsIFNvbj46OnR5cGUpLm5hbWUoKSA8PCBzdGQ6OmVuZGw7CgogICAgcmV0dXJuIDA7Cn0=