在编译我的使用(或尝试使用)某种“递归”模板定义的程序时,我遇到了一个小问题。让我尝试举一个例子。
说我有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
请注意,A
和Filter
类都可以迭代。鉴于此,我假设我们可以定义以下函数...
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图形库的人来说,可以使用类似的概念(过滤后的图形)。
有人可以给我更多详细信息吗?
答案 0 :(得分:1)
问题在于您的函数不会在“编译时”停止其递归,因此即使std::distance(foo.begin(), foo.end()) == 0
,bar(foo)
也需要实例化。
因此必须实例化
bar<Iterable>
bar<PositiveFilter<Iterable>>
bar<PositiveFilter<PositiveFilter<Iterable>>>
可能有几种解决方法:
请勿将正类型范围更改为无效范围。仅修改原始范围。仅将原始范围传递给函数。
修改过滤器,以便应用两次过滤器不会更改类型:
-> PositiveFilter<PositiveFilter<Iterable>>
是PositiveFilter<Iterable>
。