0

在英特尔 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)
4

2 回答 2

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
于 2012-08-12T08:38:50.747 回答
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;
于 2012-08-12T08:57:19.147 回答