在英特尔Cilk Plus扩展中,有一个关键字cilk_for(或实际上是_Cilk_for)。它就像关键字for,但更具限制性,并且它的迭代并行运行。我本着BOOST_FOREACH的精神编写了一个便利宏,它在内部使用了cilk_for。你能看到以下实施中的任何问题吗?
#pragma once
#include <iterator>
#include <boost/preprocessor/cat.hpp>
#include <cilk/cilk.h>
#define cilk_foreach(_decl_var_, _expr_range_) \
CILK_FOREACH_I(_decl_var_, _expr_range_, __COUNTER__)
#define CILK_FOREACH_I(_decl_var_, _expr_range_, _id_) \
CILK_FOREACH_II(_decl_var_, \
_expr_range_, \
BOOST_PP_CAT(_range_3s236dw221GyVcf46_, _id_), \
BOOST_PP_CAT(_end_5Y60u42bIp7DZd88f2c_, _id_), \
BOOST_PP_CAT(_itr_6V970q8n4Etv0i8bf50_, _id_), \
BOOST_PP_CAT(_continue_4rtWH641r5cXqU_, _id_))
#define CILK_FOREACH_II(_decl_var_, _expr_range_, _range_, _end_, _itr_, _cont_) \
auto&& _range_ = _expr_range_; \
auto _end_ = std::end(_range_); \
\
cilk_for (auto _itr_ = std::begin(_range_); _itr_ != _end_; ++_itr_) \
if (auto _cont_ = true) \
for (_decl_var_ = *_itr_; _cont_; _cont_ = false)
你会像这样使用它:
std::vector<int> values (10);
cilk_foreach (auto& value , values)
{
value += 123;
}
修改
template <typename T>
struct Wrap
{
T& data;
explicit Wrap(T&& data)
: data (data)
{}
operator bool() const
{
return true;
}
};
template <typename T>
Wrap<T> wrap(T&& data)
{
return Wrap<T>(std::forward<T>(data));
}
#define cilk_foreach(_decl_var_, _expr_range_) \
CILK_FOREACH_I(_decl_var_, _expr_range_, __COUNTER__)
#define CILK_FOREACH_I(_decl_var_, _expr_range_, _id_) \
\
CILK_FOREACH_II(_decl_var_, \
_expr_range_, \
BOOST_PP_CAT(_range_3s236dw221GyVcf46_, _id_), \
BOOST_PP_CAT(_itr_6V970q8n4Etv0i8bf50_, _id_), \
BOOST_PP_CAT(_continue_4rtWH641r5cXqU_, _id_))
#define CILK_FOREACH_II(_decl_var_, _expr_range_, _range_, _itr_, _cont_) \
\
if (auto _range_ = wrap(_expr_range_)) \
cilk_for (auto _itr_ = std::begin(_range_.data); \
_itr_ != std::end (_range_.data); \
++_itr_) \
if (auto _cont_ = true) \
for (_decl_var_ = *_itr_; _cont_; _cont_ = false)
答案 0 :(得分:3)
你应该读这个:C++ Boost: Any gotchas with BOOST_FOREACH?
一个明显的问题是你的marco没有扩展到具有它看起来像它的词汇类型的东西。例如,考虑
if(condition)
cilk_foreach (auto& value , values) {
//stuff
}
甚至更糟
if(condition)
cilk_foreach (auto& value , values)
// one-line stuff
else
// other stuff
答案 1 :(得分:2)
Hurkyl的答案是正确的,为了防止这个错误我使用这个宏:
#define foreach(ARRAY, ITEM) \
for (size_t i = 0, b = 1; b && i != (ARRAY).size(); ++i, b = !b) \
for (auto &ITEM = (ARRAY)[i]; b; b = 0)
是的,它有一些缺点,但确实暴露了真正的for循环行为,即使嵌套在另一个答案中也是如此。按预期打破并继续工作。
你会像这样使用它:
std::vector<int> values(10);
foreach (values, val)
val += 123;