我有以下宏:
#define FOREACH(decl, c) BOOST_FOREACH(decl, std::make_pair((c).begin(), (c).end()))
(我正在使用这个宏,因为我的容器没有实现可变迭代 API。)
它的问题在于它c
被评估了两次。
我的问题是可以修复这个宏,以便:
c
最多评估一次- 为了满足第一个条件而创建的任何局部变量仅存在于各自的 foreach 范围内。
我有以下宏:
#define FOREACH(decl, c) BOOST_FOREACH(decl, std::make_pair((c).begin(), (c).end()))
(我正在使用这个宏,因为我的容器没有实现可变迭代 API。)
它的问题在于它c
被评估了两次。
我的问题是可以修复这个宏,以便:
c
最多评估一次您可以使用内联辅助函数。
#define FOREACH(decl, c) BOOST_FOREACH(decl, pair_helper(c))
template <typename T>
inline std::pair<typename T::iterator, typename T::iterator> pair_helper (T c) {
return std::make_pair(c.begin(), c.end());
}
不需要这种骇客。Boost.Foreach 依赖 Boost.Range 来检索迭代器。有两种方法可以扩展它:
现在,在您的情况下,您似乎提供了begin()
andend()
成员函数,但不提供嵌套类型iterator
(我假设这就是可变迭代 API 的意思)。你可以做两件事之一。
首先,您可以typedef
像这样嵌套迭代器类型:
typedef const_iterator iterator;
其次,如果你不能修改类,你可以专门化元函数,像这样(用你的容器类型替换 YourContainer):
namespace boost
{
//
// Specialize metafunctions. We must include the range.hpp header.
// We must open the 'boost' namespace.
//
template< >
struct range_mutable_iterator< YourContainer >
{
typedef YourContainer::const_iterator type;
};
template< >
struct range_const_iterator< YourContainer >
{
typedef YourContainer::const_iterator type;
};
} // namespace 'boost'
当然,我假设您const_iterator
typedef
的班级中有 'd (因为您说它不支持可变)。如果你不这样做,你将需要YourContainer::const_iterator
用你的任何类型替换const_iterator
。
'Statement-expressions' 是一个gcc/g++ 扩展以避免重复计算宏参数
#define make_pair_of_iterators(c) ({typeof(c)& c_ = (c); make_pair(c_.begin(), c_.end()); })
然后你可以这样做:
#define FOREACH(decl, c) BOOST_FOREACH(decl, make_pair_of_iterators(c) )
(并且typeof
也是 gcc/g++ 扩展。)