代码之家  ›  专栏  ›  技术社区  ›  John WH Smith

这个递归模板是有效C++吗?

  •  -1
  • John WH Smith  · 技术社区  · 6 年前

    我在编译一个使用(或试图使用)某种“递归”模板定义的程序时遇到了一个小问题。我来举个例子。

    说我有课 A 它是某种容器, Filter 在集合上提供“过滤”迭代器的类(有些元素是基于谓词跳过的,与使用 if 关键字)。

    让我们来定义 A<int> 包含整数,以及 PositiveFilter<A<int>> 它可以迭代并将跳过 实例。如果我们采用这个程序:

    A<int> foo = {-1, 0, 1}; /* Let's assume I can init. this way */
    PositiveFilter< A<int> > positives(foo);
    for(auto const i : positives) std::cout << i << std::endl;
    

    输出将是:

    0
    1
    

    让我们注意到 滤波器 类可以迭代。鉴于此,我假设我们可以定义以下函数…

    template<typename Iterable>
    void bar(Iterable& c) {
        for(auto const i : c) std::cout << i << std::endl;
    
        /* TODO: randomly change the sign of elements in c */
    
        typedef PositiveFilter<Iterable> SubPositiveFilter;
        SubPositiveFilter foo(c);
    
        /* Let's assume iterator difference is properly implemented in filters */
        if(std::distance(foo.begin(), foo.end()) == 0) return;
        bar(foo);
    }
    

    …然后做一些像…

    A<int> foo = {-1, 0, 1};
    bar(foo);
    

    …看着我的代码运行直到随机性厌倦它。

    基本上我感兴趣的是这个递归定义 PositiveFilter 越过 正滤器 越过 正滤器 S […]结束 我想我可能在我的代码中犯了一些错误(事情超出范围,输入错误,…),但是如果我们能把它放在一边, 我想知道这个“递归”类型化的过滤器是否有效 .

    我试过在一个更大的项目中进行,但是 g++ 开始占用我所有的CPU时间。回到上面的例子,我的理论是它试图定义…

    A<int>
    PositiveFilter<A<int>>
    PositiveFilter<PositiveFilter<A<int>>>
    PositiveFilter<PositiveFilter<PositiveFilter<A<int>>>>
    ...
    

    直到我的电脑从无限循环中崩溃。在我的例子中,当使用coin-or's lemon图形库时,问题就出现了,它提供了图形适配器,允许我对图形的特定元素进行迭代。在函数中,我递归地在适配器上定义适配器,直到子图中满足某个停止条件为止。对于那些熟悉Boost的图形库的人,可以使用类似的概念(过滤图形)。

    有人能告诉我更多的细节吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Jarod42    6 年前

    问题是你的函数不会在“编译时”停止递归,所以即使 std::distance(foo.begin(), foo.end()) == 0 , bar(foo) 需要实例化。

    所以它必须实例化

    • bar<Iterable>
    • bar<PositiveFilter<Iterable>>
    • bar<PositiveFilter<PositiveFilter<Iterable>>>

    有几种解决办法:

    • 不要将正类型的范围修改为无效范围。仅修改原始范围。仅将原始范围传递给函数。

    • 修改过滤器,使应用两次过滤器不会更改类型:
      -gt; PositiveFilter<PositiveFilter<Iterable>> PositiveFilter<Iterable> .