
给定由Node<>类型的非终端节点表示的树.和A,B等任意类型的终端节点(见下文).
因为我不想使用runtime-polymorphism,所以我喜欢通过constexpr函数将树转换为std :: tuple,就像下面示例中的立即调用的lambda表达式一样.
struct A {};struct B {};struct C {};struct D {};struct E {};template<typename... T>struct Node { constexpr Node(const T&... n) : mChildren{n...} {} std::tuple<T...> mChildren;};template<uint8_t N>struct IndexNode { std::array<uint8_t,N> mChildren;};int main() { constexpr auto tree = []() { auto t = Node(A(),B(),Node(C(),Node(D())),E()); // transform t into std::tuple<A,B,C,D,IndexNode<1>{3},IndexNode<2>{2,4},E,IndexNode<4>{0,1,5,6}> // return ...; }();} 我们的想法是使用元组元素的索引作为树的活动(选定)节点的“指针”.总体目的是在μC上实现菜单系统,而不使用运行时多态性.
如果我可以在编译时执行这个转换,我可以使用一个特殊的元函数来检索活动的元组元素并在其上调用一些函数.我已经写过这个功能了.
缺少的链接肯定会是某种深度优先的树遍历……但我无法弄明白.
解决方法 如何使用大量的std :: tuple_cat,std :: index_sequence和递归如下?#include <tuple>#include <array>#include <iostream>struct A {};struct B {};struct C {};struct D {};struct E {};template <typename... T>struct Node { constexpr Node (T const & ... n) : mChildren { n... } { } std::tuple<T...> mChildren; };template <std::size_t N>struct IndexNode { std::array<uint8_t,N> mChildren; };template <typename>struct cntT : public std::integral_constant<std::size_t,1U> { };template <typename ... Ts>struct cntT<Node<Ts...>> : public std::integral_constant<std::size_t,1U + (cntT<Ts>::value + ...)> { };template <typename T>struct getT { constexpr auto operator() (T const & t,std::size_t & cnt) { ++cnt; return std::make_tuple(t); } };template <typename ... Ts>struct getT<Node<Ts...>> { template <std::size_t ... Is> constexpr auto func (std::tuple<Ts...> const & t,std::index_sequence<Is...> const &,std::size_t & cnt) { std::size_t val { cnt }; IndexNode<sizeof...(Ts)> in { { { uint8_t(val += cntT<Ts>::value)... } } }; return std::tuple_cat(getT<Ts>()(std::get<Is>(t),cnt)...,std::make_tuple(in)); } constexpr auto operator() (Node<Ts...> const & n,std::size_t & cnt) { return func(n.mChildren,std::make_index_sequence<sizeof...(Ts)>{},cnt); } };template <typename ... Ts>constexpr auto linearNode (Node<Ts...> const & n) { std::size_t cnt ( -1 ); return getT<Node<Ts...>>()(n,cnt); }int main() { constexpr auto tree = []() { auto t = Node { A{},B{},Node{ C{},Node{ D{} } },E{} }; return linearNode(t); }(); static_assert( std::is_same< decltype(tree),std::tuple<A,IndexNode<1>,IndexNode<2>,IndexNode<4>> const>::value,"!"); std::cout << "IndexNode<1> { "; for ( auto const & v : std::get<4U>(tree).mChildren ) std::cout << int(v) << ","; std::cout << "}" << std::endl; // print IndexNode<1> { 3,} std::cout << "IndexNode<2> { "; for ( auto const & v : std::get<5U>(tree).mChildren ) std::cout << int(v) << ","; std::cout << "}" << std::endl; // print IndexNode<2> { 2,4,} std::cout << "IndexNode<4> { "; for ( auto const & v : std::get<7U>(tree).mChildren ) std::cout << int(v) << ","; std::cout << "}" << std::endl; // print IndexNode<4> { 0,6,} } 总结 以上是内存溢出为你收集整理的c – 将树编译成元组的编译时间全部内容,希望文章能够帮你解决c – 将树编译成元组的编译时间所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)