2015-10-05 55 views
0

有人可以改进我的可怕执行are_siblings下面?这只是猜测所有可能的父母,然后决定这两个班是否是基于这些家长候选人的兄弟姐妹。检测两个类是兄弟

#include <type_traits> 

template <bool...> struct Or; 

template <bool First, bool... Rest> 
struct Or<First, Rest...> : std::conditional<First, 
    std::true_type, Or<Rest...>>::type {}; 

template <> 
struct Or<> : std::false_type {}; 

template <typename T, typename U, typename... Parents> 
struct are_siblings : 
    Or<(std::is_base_of<Parents, T>::value && std::is_base_of<Parents, U>::value 
    && !std::is_base_of<T,U>::value && !std::is_base_of<U,T>::value)...> {}; 

// Test 
#include <iostream> 

struct A {}; 
struct B : A {}; 
struct C : A {}; 
struct D : A, C {}; 
struct E : B, C {}; 

int main() { 
    std::cout << std::boolalpha << are_siblings<D,E, A,B,C>::value << '\n'; // true 
    std::cout << are_siblings<C,D, A,B,E>::value << '\n'; // false 
    std::cout << are_siblings<B,E, A,B,E>::value << '\n'; // false 
} 

如果有一种方法可以在编译时获得一个类的所有父母,那么这将解决我认为的问题。

更新: 下面就不再需要在家长考生猜想,但最好是有不依赖于定义parents成员类型的类的解决方案?

#include <type_traits> 
#include <tuple> 

template <bool...> struct Or; 

template <bool First, bool... Rest> 
struct Or<First, Rest...> : std::conditional<First, 
    std::true_type, Or<Rest...>>::type {}; 

template <> 
struct Or<> : std::false_type {}; 

template <typename T, typename U, typename Parents> struct are_siblings_helper; 

template <typename T, typename U, template <typename...> class P, typename... Parents> 
struct are_siblings_helper<T, U, P<Parents...>> : 
    Or<(std::is_base_of<Parents, T>::value && std::is_base_of<Parents, U>::value 
    && !std::is_base_of<T,U>::value && !std::is_base_of<U,T>::value)...> {}; 

template <typename, typename> struct merge; 

template <template <typename...> class P, typename... Ts, typename... Us> 
struct merge<P<Ts...>, P<Us...>> { 
    using type = P<Ts..., Us...>; 
}; 

template <typename T, typename U> 
struct are_siblings : are_siblings_helper<T,U, 
    typename merge<typename T::parents, typename U::parents>::type> {}; 

// Test 
#include <iostream> 

struct A {}; 

struct B : virtual A { 
    using parents = std::tuple<A>; 
}; 

struct C : virtual A { 
    using parents = std::tuple<A>; 
}; 

struct D : virtual A, C { 
    using parents = std::tuple<A,C>; 
}; 

struct E : virtual B, virtual C { 
    using parents = std::tuple<B,C>; 
}; 

int main() { 
    std::cout << std::boolalpha << are_siblings<D,E>::value << '\n'; // true 
    std::cout << are_siblings<C,D>::value << '\n'; // false 
    std::cout << are_siblings<B,E>::value << '\n'; // false 
} 

进一步更新: 如果你有兴趣,你可以检查,其中该项目与此更新的代码标题:
http://ideone.com/UQJ3WZ

std::is_base_of甚至没有被使用在所有了!它似乎是一个完成的重要项目,我会尽力完成自己的。

+1

我很好奇你为什么要这样做。你想解决什么问题? – Dai

+2

首先,定义“兄弟姐妹”。 –

+0

至少有一个共同的父亲,但一个不是从另一个的后裔? – prestokeys

回答

1

“有没有一种解决方案不依赖于类的定义parents成员类型”-在纯C++中通常更加方便。 (其他选项相当于记录您的成员直接加入的相同类型的信息 - 例如在类型特征中;如果您想查看人们被黑客攻击了什么,请搜索“C++ introspection library”或“C++反射库”)。

有一些工具可以输出抽象语法树表示(例如clang/llvm),然后可以通过创建C++代码的工具读取/处理它,但将它们引入到构建过程中是相对较少的。