将BOOST_FOREACH与恒定的侵入性列表一起使用
Using BOOST_FOREACH with a constant intrusive list
请考虑使用以下代码使用 BOOST_FOREACH 宏遍历侵入性列表:
#include <boost/foreach.hpp>
#include <boost/intrusive/list.hpp>
typedef boost::intrusive::list<
boost::intrusive::list_base_hook<> > MyList;
void iterate (const MyList& xs) {
BOOST_FOREACH (MyList::const_reference node, xs);
}
int main () {
MyList xs;
iterate (xs);
return 0;
}
给定 boost 版本 1.48,代码在 clang 3.2 (SVN) 和 gcc 4.6.3 中失败,但适用于 gcc 4.5.3。使用非常量限定参数xs
iterate
代码工作。启用 C++11 后,所有编译器都接受代码。当使用boost-1.46时,两个gcc版本都接受代码,但clang仍然不接受。
手头的代码是对BOOST_FOREACH
宏的误用,还是提升端的错误?有没有比常规 for 循环迭代更好的解决方法?
编辑:我将错误消息粘贴到 GCC 和 clang 的 pastebin (两者都非常冗长)。
以下是我可以从日志中收集的内容以及我对失败原因的推断。
简短版本:由于某种原因,BOOST_FOREACH
尝试复制不可能的数据。
"扩展性"页上有一个注释:
使
BOOST_FOREACH
使用不可复制的序列类型对于不可复制的序列类型,我们需要告诉
BOOST_FOREACH
不要尝试复制。如果我们的类型继承自boost::noncopyable
,则不需要进一步的操作。如果没有,我们必须专门化boost::foreach::is_noncopyable<>
模板 [...]实现相同效果的另一种方法是覆盖全局boost_foreach_is_noncopyable()
函数。这样做的优点是可以移植到较旧的编译器。
从诊断来看,目前还不清楚类型是否配置正确,因此您可能需要试一试。
<小时 />修剪诊断和分析。
/usr/include/boost/foreach.hpp:571:37: error: no matching constructor for initialization of 'boost::intrusive::list< >'
::new(this->data.address()) T(t);
^ ~
/usr/include/boost/foreach.hpp:648:51: note: in instantiation of member function 'boost::foreach_detail_::simple_variant<boost::intrusive::list< > >::simple_variant' requested here
return auto_any<simple_variant<T> >(*rvalue ? simple_variant<T>(t) : simple_variant<T>(&t));
^
/usr/include/boost/intrusive/list.hpp:1490:35: note: candidate constructor not viable: 1st argument ('const boost::intrusive::list< >') would lose const qualifier
BOOST_MOVABLE_BUT_NOT_COPYABLE(list)
^
/usr/include/boost/move/move.hpp:371:7: note: expanded from macro 'BOOST_MOVABLE_BUT_NOT_COPYABLE'
TYPE(TYPE &);
/usr/include/boost/intrusive/list.hpp:1497:4: note: candidate constructor not viable: no known conversion from 'const boost::intrusive::list< >' to 'const value_traits' (aka 'const boost::intrusive::detail::base_hook_traits<boost::intrusive::list_base_hook< >, boost::intrusive::list_node_traits<void *>, 1, boost::intrusive::default_tag, 1>') for 1st argument;
list(const value_traits &v_traits = value_traits())
^
/usr/include/boost/intrusive/list.hpp:1506:4: note: candidate constructor not viable: no known conversion from 'const boost::intrusive::list< >' to '::boost::rv<list< >> &' for 1st argument;
list(BOOST_RV_REF(list) x)
^
/usr/include/boost/intrusive/list.hpp:1502:4: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
list(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
^
我试图尽可能多地隔离错误(删除回溯等)。显然问题源于 boost::intrusive::list
,更准确地说是无法从boost::intrusive::list<> const
构建新boost::intrusive::list<>
。
最有前途的构造函数由宏定义:
BOOST_MOVABLE_BUT_NOT_COPYABLE(list)
扩展到
list(list&);
这是 boost 在 C++03 中模拟不可复制类型的移动语义的方式。但是,它不能从const
项中移动,因为const
限定符将丢失。
这似乎是BOOST_FOREACH
用来避免容器参数的多重评估(如果是函数调用)的技巧的一部分,尽管我有点惊讶它试图在这里复制参数。
由于您使用的是 gcc> 4.6 和 clang 3.2,因此您可以使用 C++11 的基于范围的 looops:
#include <boost/foreach.hpp>
#include <boost/intrusive/list.hpp>
typedef boost::intrusive::list<
boost::intrusive::list_base_hook<> > MyList;
void iterate (const MyList& xs) {
for(const auto &node : xs) {
// do something with node
}
}
int main () {
MyList xs;
iterate (xs);
return 0;
}
您也可以使用std::for_each
:
void iterate (const MyList& xs) {
std::for_each(xs.begin(), xs.end(),
[](MyList::const_reference node) {
// do something with node
}
);
}
- 当返回语句时,逗号运算符、大括号初始化列表和 std::unique_ptr 组合在一起
- 与引用一起使用的列表,在用作成员时更改行为
- 与lambda一起使用虚拟继承在初始化列表中捕获此问题的GCC错误
- 将[]运算符与链接列表一起使用
- 当将 getline 与 int 一起使用时,如何修复"没有重载函数 'getline' 的实例与参数列表匹配"
- 如何将重新绑定与自定义分配器和自定义列表一起使用
- 如何将 2 个链表合并或合并在一起以创建新列表
- 常量变量初始化仅与成员初始化列表一起工作
- 将initalizer列表与从空基类继承的结构一起使用
- 具有与专用列表一起使用的参数列表的超类方法<superclass>
- 为什么 auto 关键字不能与指向函数的指针的初始化列表一起使用?
- 如何将列表语法与默认精神一起使用
- 使初始化列表与 C++ 中的继承一起使用
- 将 clang 3.1 与初始值设定项列表一起使用
- 将BOOST_FOREACH与恒定的侵入性列表一起使用
- 如何将 auto 与初始值设定项列表一起使用push_back
- 如何使用与成员初始化器列表一起使用的static_assert
- boost DFS不能与set垂直列表一起工作
- STL算法可以与循环列表一起使用吗?
- 将字符串的填充构造函数与初始值设定项列表一起使用