检测两个班级是否是兄弟姐妹

时间:2015-10-05 23:57:21

标签: c++ templates c++11 variadic

有人可以改进我下面mDocument.select("input[src*=Btn],img[src*=Btn]:not(img[src*=notThisOne])") 的可怕实施吗?它只是猜测所有可能的父母,然后决定这两个班级是否是基于这些父母候选人的兄弟姐妹。

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

进一步更新 如果您有兴趣,可以使用此更新的代码检查此项目的前进方向:
http://ideone.com/UQJ3WZ

#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 } 甚至不再被使用了!它看起来是一个完成的重大项目,我将尝试自己完成。

1 个答案:

答案 0 :(得分:1)

&#34;是否有一个解决方案不依赖于定义parents成员类型的类&#34; - 在纯C ++中通常更方便。 (其他选项相当于记录您的parents成员直接添加的相同类型的信息 - 例如在类型特征中;搜索&#34; C ++内省库&#34;或者#34; C ++反射库&#34;如果你想看看人们被黑客攻击了什么。)

有些工具可以输出抽象语法树表示(例如clang / llvm),然后可以通过创建C ++代码的工具读取/处理它们,但它们很少值得将它们引入构建过程....