如何有效地从嵌套表达式生成所有类型的元组?

什么时候

假设我有一些包含类型排列的模板表达式,在这种情况下,它们来自抽象语法树

template <typename... Children>                                                    
struct Branch                                                                      
{                                                                                  
};                                                                                 

template <int param>                                                               
struct Leaf                                                                        
{                                                                                  
};

输入表达式可以是BranchLeaf类型的任何嵌套组合,但为简单起见,我将创建一个线性AST,其中包含一个深层类型的单个Leaf包装NBranch

using Expression =
  Branch<
    Branch<
      Leaf>>; // N = 2

为了解决这个问题,我创建了一个动态生成这些表达式的函数,因此我可以演示绘图存在的问题。所以这是我将用来生成表达式的函数:

// wrap Leaf in Branch N number of times:
template <int N, typename T = Leaf>
struct Nest
{
    using type = typename Nest<N-1, Branch<T>>::type;
};

template <typename T>
struct Nest<0, T>
{
    using type = T;
};

N = 25的实时示例

请注意,该解决方案应适用于分支和叶子的任何组合,包括每个分支的多个分支/叶子组合,而不仅适用于由创建的有限集Nest我只是用Nest它来生成下面的图而无需手动写出大的表达式。现在,我的问题是,如何有效地从该表达式中提取所有实例化Branch类型?

因此,对于N == 2,如上所示,我希望将以下内容作为输出:

std::tuple<
  Branch<Branch<Leaf>>,
  Branch<Leaf>>;

这并不一定是一个元组,它可以是任何东西,但它确实必须能够接受任何数量的类型,而严重的两轮牛车,这样boost::mpl类型的问题了,至少和Boost 1.56为了这个问题,我将使用元组。

到目前为止,这是我所做的:

namespace detail
{

// a container of types
template <typename... T> struct Types {};

template <typename T, typename Enabled = void>
struct UnfoldImpl;

template <template <typename...> class Branch, typename... Children>
struct UnfoldImpl<
    Types<Branch<Children...>>,
    typename std::enable_if<Branch<Children...>::IsBranch::value>::type>
{
    using type = typename TupleCat<
        std::tuple<Types<Branch<Children...>>>,
        typename UnfoldImpl<Types<Children...>>::type>::type;
};

template <typename Leaf>
struct UnfoldImpl<
    Types<Leaf>,
    typename std::enable_if<!Leaf::IsBranch::value>::type>
{
    using type = std::tuple<>;
};

template <typename FirstBranch, typename... OtherBranches>
struct UnfoldImpl<Types<FirstBranch, OtherBranches...>,typename std::enable_if<sizeof...(OtherBranches)>::type>
{
    using type = typename TupleCat<
        typename UnfoldImpl<Types<FirstBranch>>::type,
        typename UnfoldImpl<Types<OtherBranches...>>::type>::type;
};

}

// Take an expression containing some combination of branch and leaf classes, and extract every
// type that is a template instantiation of Branch and place it into a tuple.
template <typename Expression>
struct Unfold : detail::UnfoldImpl<detail::Types<Expression>> {};

此处可以看到完整的程序,该程序实例化表达式,然后实例化分支类型

我对Unfold作品的实施,但效率似乎非常低下。以下是使用GCC 4.9.1(仅带有std=c++11标志)并使用以下命令进行编译时的总驻留内存time -v g++ -std=c++11 main.cpp

峰值驻留内存与表达深度

红线表示time -v gcc ...仅生成表达式(即实例化Nest<N>::typein中的main())时在编译过程中的峰值驻留内存(由衡量),蓝线表示将类型的实例添加到Unfold<Expression>::type其中,其中Expression的输出是Nest<N>

我很高兴红线显示为常数,这表明编译器在这里可能做得不错。但是,蓝线显然是多项式,我想知道是否有任何简便的方法可以将其降低,理想情况下降低为线性,尽管Nlog(N)也很好。

我的问题是:如何将效率提高Unfold到比O(N ^ 2)好?

我已经问过这个问题的一般形式(如何减少大型模板的编译时内存占用量?),但是我在将这些解决方案应用于这种特殊情况时遇到了麻烦,希望能获得一些指导。

哥伦布

黄金法则是简化。并且不要使用tuple

template <typename...> struct type_list {using type = type_list;};

template<typename...>
struct cat_type_list;

template<typename T>
struct cat_type_list<T> : T {};

template<typename... T, typename... U, typename... R>
struct cat_type_list<type_list<T...>, type_list<U...>, R...> :
    cat_type_list<type_list<T..., U...>, R...> {};


template <typename... AllBranches>
struct Unfold
{
    using type = typename cat_type_list<
        typename Unfold<AllBranches>::type...>::type;
};

template <typename T>
struct Unfold<T>
{
    using type = type_list<>;
};

template <template <typename...> class Branch, typename... Children>
struct Unfold<Branch<Children...>>
{
    using type = typename cat_type_list<
        type_list<Branch<Children...>>,
        typename Unfold<Children...>::type>::type;
};

演示一旦我将N500改为,编译所需的时间将从〜150倍增加到320ms 50

这是一张很棒的图表,显示了编译程序时GCC的峰值内存使用情况-值是由for lim in {5..800..5}; do /usr/local/bin/time -f"%M" g++ -DLIMIT=$lim -std=c++11 ~/Programming/Saves/TEMPS/TEMP2.cxx; done以下人员收集的

在此处输入图片说明

对我来说,空间复杂度似乎是线性的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何从set python有效地循环正则表达式搜索

来自分类Dev

如何生成所有有效的数字表达式?

来自分类Dev

如何有效地将字符串与许多正则表达式匹配

来自分类Dev

如何有效地传递或忽略由 python 正则表达式解析的一些标记?

来自分类Dev

Java 8使用lambda表达式捕获22并有效地最终

来自分类Dev

有效地搜索正则表达式集合

来自分类Dev

Perl,有效地使用正则表达式清理文件的问题

来自分类Dev

有效地提取大文件上的列/正则表达式

来自分类Dev

有效地确定类型

来自分类Dev

如何有效地实现std :: tuple,以便空类型的元组本身就是空类型?

来自分类Dev

如何有效地生成总和在指定范围内的所有组合(在所有深度)

来自分类Dev

如何有效地在同一字符串上应用多个正则表达式?

来自分类Dev

如何在perl中有效地解析表达式'^#[0-9A-F] {2} \ $ [0-9A-F] {4} / $'

来自分类Dev

表达式块类型有效//堆栈溢出

来自分类Dev

如何有效地语法

来自分类Dev

有效地获取节点的所有关系类型

来自分类Dev

如何使用将用numba编译的代码有效地创建长度为N的元组?

来自分类Dev

“ expect(9).be> 6”如何是有效表达式?

来自分类Dev

有效的XPath表达式

来自分类Dev

如何有效地获取Cassandra表中的所有行名?

来自分类Dev

如何有效地为List的所有元素添加前缀?

来自分类Dev

如何有效地遍历所有边缘?

来自分类Dev

如何有效地从Rails的大表中获取所有行?

来自分类Dev

如何有效地将所有栅格文件导入R?

来自分类Dev

如何有效地返回视口中的所有元素ID?

来自分类Dev

如何使用Spark有效地检查列中的所有值?

来自分类Dev

熊猫MultiIndex DataFrames HDFStore:如何有效地获取所有索引

来自分类Dev

如何有效地强制VirtualBox对所有VM文件使用/ dev / shm?

来自分类Dev

如何有效地检测PDF中的所有空白页?

Related 相关文章

  1. 1

    如何从set python有效地循环正则表达式搜索

  2. 2

    如何生成所有有效的数字表达式?

  3. 3

    如何有效地将字符串与许多正则表达式匹配

  4. 4

    如何有效地传递或忽略由 python 正则表达式解析的一些标记?

  5. 5

    Java 8使用lambda表达式捕获22并有效地最终

  6. 6

    有效地搜索正则表达式集合

  7. 7

    Perl,有效地使用正则表达式清理文件的问题

  8. 8

    有效地提取大文件上的列/正则表达式

  9. 9

    有效地确定类型

  10. 10

    如何有效地实现std :: tuple,以便空类型的元组本身就是空类型?

  11. 11

    如何有效地生成总和在指定范围内的所有组合(在所有深度)

  12. 12

    如何有效地在同一字符串上应用多个正则表达式?

  13. 13

    如何在perl中有效地解析表达式'^#[0-9A-F] {2} \ $ [0-9A-F] {4} / $'

  14. 14

    表达式块类型有效//堆栈溢出

  15. 15

    如何有效地语法

  16. 16

    有效地获取节点的所有关系类型

  17. 17

    如何使用将用numba编译的代码有效地创建长度为N的元组?

  18. 18

    “ expect(9).be> 6”如何是有效表达式?

  19. 19

    有效的XPath表达式

  20. 20

    如何有效地获取Cassandra表中的所有行名?

  21. 21

    如何有效地为List的所有元素添加前缀?

  22. 22

    如何有效地遍历所有边缘?

  23. 23

    如何有效地从Rails的大表中获取所有行?

  24. 24

    如何有效地将所有栅格文件导入R?

  25. 25

    如何有效地返回视口中的所有元素ID?

  26. 26

    如何使用Spark有效地检查列中的所有值?

  27. 27

    熊猫MultiIndex DataFrames HDFStore:如何有效地获取所有索引

  28. 28

    如何有效地强制VirtualBox对所有VM文件使用/ dev / shm?

  29. 29

    如何有效地检测PDF中的所有空白页?

热门标签

归档