我有以下宏:
#define FOREACH(decl, c) BOOST_FOREACH(decl, std::make_pair((c).begin(), (c).end()))
(我正在使用这个宏,因为我的容器没有实现可变迭代API。)
问题在于,c
被评估两次。
我的问题是这个宏可以修复,以便:
c
最多只评估一次答案 0 :(得分:8)
您可以使用内联辅助函数。
#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());
}
答案 1 :(得分:6)
没有必要这个hackery。 Boost.Foreach依赖于Boost.Range来检索迭代器。有两种方法可以扩展它:
现在在您的情况下,看起来您提供了begin()
和end()
成员函数,但是没有提供嵌套类型iterator
(我假设你的意思是可变迭代API)。你可以做两件事之一。
首先,您可以typedef
嵌套迭代器类型,如下所示:
typedef const_iterator iterator;
其次,如果你不能修改类,你可以像这样专门化元函数(用你的容器类型替换你的容器):
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
所属的任何类型。
答案 2 :(得分:2)
'Statement-expressions'是gcc/g++ extension,以避免重复评估宏参数
#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 ++扩展名。)