此递归模板类型定义有效的C ++吗?

时间:2018-09-25 16:45:49

标签: c++ templates recursion

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

说我有A类,它是某种容器,还有Filter类,它们提供对集合的“过滤”迭代器(某些元素基于谓词被跳过,就像Python的生成器具有if关键字)。

让我们定义包含整数的A<int>PositiveFilter<A<int>>,可以对其进行迭代,并跳过A实例中的所有否定元素。如果我们采用这个程序:

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

请注意,AFilter类都可以迭代。鉴于此,我假设我们可以定义以下函数...

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);

...并观看我的代码运行,直到对随机性厌倦为止。

我主要感兴趣的是这种递归定义,其中{{1}上的PositiveFilter上的PositiveFilter上的PositiveFilter上的A s。我认为我可能在代码中犯了一些错误(事情超出范围,键入错误,...),但是如果我们可以把它放在一边,我想知道这种“递归” typedef-在过滤器上设置过滤器是有效的

我曾尝试在更大的程序中执行此操作,但是g++开始占用我所有的CPU时间。回到上面的例子,我的理论是它试图定义...

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

直到我的计算机从无限循环中崩溃。就我而言,使用COIN-OR的LEMON图库时会出现问题,该库提供了图适配器,使我可以迭代图的特定元素。在一个函数中,我递归地在适配器上定义适配器,直到子图中满足某个停止条件为止。对于熟悉Boost图形库的人来说,可以使用类似的概念(过滤后的图形)。

有人可以给我更多详细信息吗?

1 个答案:

答案 0 :(得分:1)

问题在于您的函数不会在“编译时”停止其递归,因此即使std::distance(foo.begin(), foo.end()) == 0bar(foo)也需要实例化。

因此必须实例化

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

可能有几种解决方法:

  • 请勿将正类型范围更改为无效范围。仅修改原始范围。仅将原始范围传递给函数。

  • 修改过滤器,以便应用两次过滤器不会更改类型:
    -> PositiveFilter<PositiveFilter<Iterable>>PositiveFilter<Iterable>