安全地重新定义BOOST_FOREACH宏

mar*_*ark 2 c++ boost boost-foreach

我有以下宏:

#define FOREACH(decl, c) BOOST_FOREACH(decl, std::make_pair((c).begin(), (c).end()))
Run Code Online (Sandbox Code Playgroud)

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

它的问题是,它c被评估两次.

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

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

Ale*_*kiy 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());
}
Run Code Online (Sandbox Code Playgroud)


Pau*_* II 6

没有必要这个hackery.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()end()成员函数,但不提供嵌套类型iterator(我假设你的意思是可变迭代API).你可以做两件事之一.

首先,您可以typedef像这样嵌套迭代器类型:

typedef const_iterator iterator;
Run Code Online (Sandbox Code Playgroud)

其次,如果你不能修改类,你可以像这样专门化元函数(用你的容器类型替换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'
Run Code Online (Sandbox Code Playgroud)

当然我认为你const_iterator typedef的课堂上有一个'(因为你说它不支持可变).如果不这样做,则需要更换YourContainer::const_iterator您的类型const_iterator.