【发布时间】:2017-03-21 15:15:33
【问题描述】:
我在我的代码中发现了一个错误,该错误仅在我启用编译器优化 -O1 或更高版本时才会发生。我跟踪了这个错误,当启用优化时,我似乎无法在 boost 转换范围上使用 boost type_erased 适配器。我编写了这个 c++ 程序来重现它:
#include <iostream>
#include <vector>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptor/type_erased.hpp>
using namespace boost::adaptors;
using namespace std;
int addOne(int b) {
return b + 1;
}
int main(int, char**) {
vector<int> nums{ 1, 2, 3 };
auto result1 = nums | transformed(addOne) | type_erased<int, boost::forward_traversal_tag>();
auto result2 = nums | transformed(addOne);
auto result3 = nums | type_erased<int, boost::forward_traversal_tag>();
for (auto n : result1)
cout << n << " ";
cout << endl;
for (auto n : result2)
cout << n << " ";
cout << endl;
for (auto n : result3)
cout << n << " ";
cout << endl;
}
当我在没有任何优化的情况下运行这个程序时,我得到以下输出:
2 3 4
2 3 4
1 2 3
当我使用 -O1 标志运行它时,我得到以下信息:
1 1 1
2 3 4
1 2 3
我正在使用 clang++ 来编译它。我使用的 clang 版本是:
Apple LLVM 版本 8.0.0 (clang-800.0.38)
我不知道是我做错了什么,还是一个 boost/clang 错误。
编辑:
改成
type_erased<int, boost::forward_traversal_tag, const int>()
它现在可以工作了。第三个模板参数是引用类型,将引用设置为 const 会延长转换后创建的临时对象的时间跨度。
【问题讨论】:
-
从
result1的计算中删除type_erased即使经过优化也会得到正确的结果。 -
是的,我知道,这相当于 result2 是正确的。但我需要类型擦除的结果类型。我使用了 result2 和 result3 来证明两个适配器如果不一起使用也可以工作。
-
我刚刚评论了我的观察。我对范围内容的了解为零:(。使用
boost::any_iterator怎么样? -
这就是我想要做的,这就是我使用 type_erased 适配器的方式。您不能在一个迭代器上进行迭代,您需要其中的两个,一个开始和结束。范围是一对迭代器(开始和结束)。类型擦除适配器 (type_erased) 应该返回一个 boost::any_range,它是一对 boost::any_iterator。