2

我有以下宏:

#define FOREACH(decl, c) BOOST_FOREACH(decl, std::make_pair((c).begin(), (c).end()))

(我正在使用这个宏,因为我的容器没有实现可变迭代 API。)

它的问题在于它c被评估了两次。

我的问题是可以修复这个宏,以便:

  1. c最多评估一次
  2. 为了满足第一个条件而创建的任何局部变量仅存在于各自的 foreach 范围内。
4

3 回答 3

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());
}
于 2012-01-14T00:05:23.750 回答
6

不需要这种骇客。Boost.Foreach 依赖 Boost.Range 来检索迭代器。有两种方法可以扩展它:

  1. 提供成员函数和嵌套类型: http: //www.boost.org/doc/libs/1_48_0/libs/range/doc/html/range/reference/extending/method_1.html
  2. 提供独立的函数和专门的元函数:http: //www.boost.org/doc/libs/1_48_0/libs/range/doc/html/range/reference/extending/method_2.html

现在,在您的情况下,您似乎提供了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

于 2012-01-14T02:30:58.260 回答
2

'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++ 扩展。)

于 2012-01-14T00:02:50.923 回答