我有以下宏:重新定義BOOST_FOREACH宏安全
#define FOREACH(decl, c) BOOST_FOREACH(decl, std::make_pair((c).begin(), (c).end()))
(我使用這個宏,因爲我的容器不執行可變迭代API)
的問題吧,是c
被評估兩次。
我的問題是可以在這個宏固定的,因此:
c
最多一次- 爲了滿足第一個條件只生活在各自的foreach範圍內創建的任何局部變量進行評估。
我有以下宏:重新定義BOOST_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());
}
既然第二個'c'是一個誠實的變量,你可以省略那些額外的括號(除非你是某種RIAA代理)。 – 2012-01-14 00:20:50
你說得對,我只是從給定的宏複製粘貼它。固定 – 2012-01-14 00:29:12
在VS2010上,我不得不將'typename'限定添加到配對模板參數中,但是否則它工作得很好。謝謝。 – mark 2012-01-14 19:50:12
'語句表達式' 是一個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 ++的擴展也)
這個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(既然你說,它不支持可變)。如果你不這樣做,你將需要用const_iterator
的任何類型替換YourContainer::const_iterator
。
最好避免這種類型的宏hackery,並在迭代時使用迭代語句(或算法函數模板)。 – 2012-01-13 23:45:09
@mark,它是否必須嚴格C++ 03。例如,你會允許g ++特定的擴展嗎? – 2012-01-13 23:56:41
@Aaron - 我使用VS2010。所以g ++細節不在範圍之內。 – mark 2012-01-14 09:46:14