【发布时间】:2013-01-16 19:48:05
【问题描述】:
我想做以下事情:
std::vector<int> a = {1,2,3}, b = {4,5,6}, c = {7,8,9};
for(auto&& i : join(a,b,c)) {
i += 1
std::cout << i; // -> 2345678910
}
我尝试使用boost::range::join,效果很好:
auto r = boost::join(a,b);
for(auto&& i : boost::join(r,c)) {
i += 1;
std::cout << i; // -> 2345678910
}
链式连接,读取操作工作:
for(auto&& i : boost::join(boost::join(a,b),c))
std::cout << i; // -> 123456789
但是,写作不起作用:
for(auto&& i : boost::join(boost::join(a,b),c)) {
i += 1; // Fails :(
std::cout << i;
}
我的可变参数连接也有同样的问题,即适用于阅读但不适用于写作:
template<class C> C&& join(C&& c) { return c; }
template<class C, class D, class... Args>
auto join(C&& c, D&& d, Args&&... args)
-> decltype(boost::join(boost::join(std::forward<C>(c), std::forward<D>(d)),
join(std::forward<Args>(args)...))) {
return boost::join(boost::join(std::forward<C>(c), std::forward<D>(d)),
join(std::forward<Args>(args)...));
}
Mehrdad 在 cmets 中给出了解决方案
template<class C>
auto join(C&& c)
-> decltype(boost::make_iterator_range(std::begin(c),std::end(c))) {
return boost::make_iterator_range(std::begin(c),std::end(c));
}
template<class C, class D, class... Args>
auto join(C&& c, D&& d, Args&&... args)
-> decltype(boost::join(boost::join(boost::make_iterator_range(std::begin(c),std::end(c)),
boost::make_iterator_range(std::begin(d),std::end(d))),
join(std::forward<Args>(args)...))) {
return boost::join(boost::join(boost::make_iterator_range(std::begin(c),std::end(c)),
boost::make_iterator_range(std::begin(d),std::end(d))),
join(std::forward<Args>(args)...));
}
【问题讨论】:
-
这个 可能 工作(但归功于 jrok,因为他解释了问题背后的原因):
boost::join(boost::join(boost::make_iterator_range(a.begin(), a.end()), boost::make_iterator_range(b.begin(), b.end())), boost::make_iterator_range(c.begin(), c.end())) -
@Mehrdad 谢谢,它有效!我将用解决方案更新问题。你能解释一下它为什么起作用吗? boost::make_iterator_range 也返回一个左值,所以应该选择 join 的 const ref 重载,对吧?
-
是的。这是因为 range
a是 容器本身,而像vector这样的 const 容器会将其 const 特性传播到其元素上。另一方面,iterator range 不是容器——它只是一对迭代器。并且迭代器的 const-ness 与迭代器指向的 const-ness 完全无关。另一方面,虽然我对此不确定,但我认为将boost::make_iterator_range(a.begin(), a.end())替换为boost::make_iterator_range(a)也可能有效。 -
仅作记录 - 如果您只使用左值,您的
join模板也可以工作(重命名后,带有两个参数的调用与boost::join不明确)。 -
@jrok 您是指标记为解决方案的包装器还是上一个? (上一个有同样的初始问题)