自从我更新为1.58和VS2013以来,我一直在软件中看到崩溃.只有在编译器优化开启时,我们才会看到崩溃.使用boost 1.55,没有崩溃.我设法隔离了我所看到的问题boost::any_range
以及我们如何使用它.
请参阅下面的示例代码:
#include <boost/range/any_range.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <vector>
#include <memory>
#include <cstdio>
class DummyElement
{
public:
float f_;
};
using ElementRange = boost::any_range < DummyElement*, boost::bidirectional_traversal_tag >;
using DummyElementUPtr = std::unique_ptr < DummyElement > ;
class BoostAnyTest
{
public:
BoostAnyTest()
{
for (int i = 0; i < 10; ++i)
{
auto element = DummyElementUPtr(new DummyElement());
_tprintf(_T("BoostAnyTest::ctor() 0x%p\n"), element.get());
c_.emplace_back(std::tuple<Int, DummyElementUPtr>(i, std::move(element)));
}
}
public:
ElementRange GetAll();
private:
using _ContainerType = std::vector < std::tuple<Int, std::unique_ptr<DummyElement>> > ; …
Run Code Online (Sandbox Code Playgroud) 我有一个std::multimap
,我想创建一个boost::iterator_range
从equal_range
.我在文档中找不到简单的方法,所以我尝试了以下方法:
typedef std::multimap<int, std::string> Map;
Map map;
...
boost::iterator_range<Map::iterator> r(map.equal_range(2));
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,它的工作原理(使用GCC 4.1.2).我很好奇它是如何工作的.我发现iterator_range
构造函数没有重载会发生这种情况,multimap::iterator_range
显然没有返回Boost范围的重载.
基于C++ 11范围的for循环取消引用迭代器.这是否意味着使用它没有意义boost::adaptors::indexed
?例:
boost::counting_range numbers(10,20);
for(auto i : numbers | indexed(0)) {
cout << "number = " i
/* << " | index = " << i.index() */ // i is an integer!
<< "\n";
}
Run Code Online (Sandbox Code Playgroud)
我总是可以使用计数器,但我喜欢索引迭代器.
Boost的any_range文档说明如下:
尽管底层
any_iterator
是最快的可用实现,但any_range
由于实现递增,递减,提前,等等所需的虚函数调用的成本,性能开销仍然可观.等等.通常,更好的设计选择是转换为规范形式.
作者的"规范形式"是什么意思?有人能举个例子吗?
编辑: 正如这里建议的那样,我在提升用户的邮件列表上提出了同样的问题.以下是本文原作者Neil Groves不得不说:
例如,将范围复制到矢量中.
是的,这正是我在编写文档时考虑的替代设计.迭代any_range的开销非常大,并且通常与将具体结果类型复制到诸如向量之类的容器中相比较差.但是,情况并非总是如此,并且Boost.Range的一些用户希望能够实现对any_range实例进行操作的算法.这有时是期望的,例如,允许从支持各种容器的共享库中暴露算法.any_range的使用也可能有意义,其中范围内的遍历数量很小,但底层容器的内存大小非常大.
在许多情况下,性能开销无关紧要.我想确保我没有误导任何人广泛采用any_range用法.我相信这个类的有效用法很少,但有时候它正是正确的设计选择.我将在适当的时候通过一些额外的澄清和示例来改进文档.
是否可以/可实现否定升压滤波适配器,例如
std::vector<int> v = {1, 2, 3, 4, 5};
for(auto i : v | !filtered(is_even))
std::cout << i << std::endl; // prints 1,3,5
Run Code Online (Sandbox Code Playgroud)
而不是在lambda表达式中做出否定?
动机:我使用过滤和lambda函数工作很多,但是当我不止一次使用过滤器时,我通常将它重构为自定义过滤器,例如
for(auto i : v | even) // note: my filters are more complex than even.
std::cout << i << std::endl; // prints 2,4
Run Code Online (Sandbox Code Playgroud)
现在,当我需要否定时,我正在为它们构建一个自定义过滤器,例如
for(auto i : v | not_even)
std::cout << i << std::endl; // prints 1,2,3
Run Code Online (Sandbox Code Playgroud)
但我会发现能够否定过滤器更好,例如
for(auto i : v | !even)
std::cout << i << std::endl; // prints 1,2,3
Run Code Online (Sandbox Code Playgroud) 是否存在或者如何编写一个测试类是否兼容的元函数类boost::range
?我想用这个boost::enable
成语,比如说
template <typename T>
Constructor::Constructor(const T& t, __attribute__((unused)) typename boost::enable_if<is_range_compatible<T> >::type* aux=NULL)
Run Code Online (Sandbox Code Playgroud)
为适当的is_range_compatible
元功能.我从pretty_print 了解is_container,它捕获了很多案例,但不是所有可用的东西boost::range
.
编辑这是使用C++ 03,因此我无法访问C++ 11功能.我正在使用旧的gcc 4.1和1.51.
我正在一个使用几个Boost库的项目中。查看测试报告时,我们发现测试覆盖率信息有时确实适合我们的源代码。我能够将其追踪到boost :: range。我认为这是由于库中进行了一些静态初始化,尽管我无法说得更具体些。
基本上,如果您使用编译以下代码gcc --coverage
,请运行,然后使用进行打印覆盖率报告gcov -b
,那么将有四个其他分支和另一行,我想忽略它们。
#include <boost/range.hpp>
int foo(int x)
{
return x+1;
}
int main(int argc, char* argv[])
{
return foo(argc);
}
Run Code Online (Sandbox Code Playgroud)
覆盖率报告为:已执行的行:已执行5条分支的100.00%:已执行4条的100.00%至少被执行一次:已执行4条呼叫的50.00%已执行2条呼叫:已创建2条的100.00%创建'test_gcov.cpp.gcov'
我猜这5行的计数来自两个函数签名,函数主体和boost :: range库中的另一行。我不知道确切在哪里,但是生成的gcov文件显示正在进行一些静态初始化,所以我猜那是分支所在的位置。
我想知道是否有一种方法可以告诉gcov忽略boost名称空间中的任何代码,或任何其他方式。
我想编写一个 boost 适配器放在适配器链的末尾以创建一个集合,如下所示:
set<string> s = input | filtered(...) | transformed(...) | to_set;
Run Code Online (Sandbox Code Playgroud)
使用方法 3.1,我编写了下面的代码,该代码似乎按预期工作:
namespace detail
{
struct to_set_forwarder
{
};
};
template <class R> inline auto operator|(R& r, detail::to_set_forwarder)
{
return set<R::value_type>(r.begin(), r.end());
}
template <class R> inline auto operator|(const R& r, detail::to_set_forwarder)
{
return set<const R::value_type>(r.begin(), r.end());
}
namespace
{
const auto to_set = detail::to_set_forwarder();
}
void F()
{
vector<string> input{ "1", "2", "3" };
auto result = input
//| boost::adaptors::filtered([](const auto& _) { return …
Run Code Online (Sandbox Code Playgroud) 我有接受std::vector
迭代器的函数,例如
typedef std::vector<Point> Points;
Points ConvexHull(Points::const_iterator first, Points::const_iterator last);
Run Code Online (Sandbox Code Playgroud)
我通常将std
迭代器传递给他们,但有时我需要使用boost
迭代器,例如boost::join
的范围迭代器。我应该如何更改函数的参数化(理想情况下没有模板),以使它们接受两个迭代器?此外,如何在每种类型中指示所需的迭代器概念?
我尝试查看boost::range
文档,但是这对我来说是非常混乱的,而且我不知道从哪里开始。
例如,我找不到之间的区别boost::range_details::any_forward_iterator_interface
和boost::range_details::any_forward_iterator_wrapper
,以及是否我应该要么使用那些指定我需要一个前向迭代。
编辑:
如果使用boost::any_range
,如何传递非常量左值引用?
例如:
template<typename T>
using Range = boost::any_range<T, boost::random_access_traversal_tag,
T, std::ptrdiff_t>;
f(Range<Point> &points); // defined elsewhere
// -------------
vector<Point> vec;
f(vec); // error; cannot bind non-const lvalue reference to unrelated type
Run Code Online (Sandbox Code Playgroud) boost-range ×10
c++ ×9
boost ×8
iterator ×3
c++11 ×2
gcov ×1
lambda ×1
std ×1
templates ×1
type-traits ×1