【问题标题】:Can BOOST_FOREACH be customized for a pointer type?可以为指针类型定制 BOOST_FOREACH 吗?
【发布时间】:2017-10-30 05:27:23
【问题描述】:

我正在编写 C++98(抱歉),但使用的是 C 库,其中有许多对象存储在以下形式的数据结构中:

struct c_container
{
    size_t len;
    int data[1];
};

struct c_container *make_container(size_t n)
{
    if (n == 0)
        return NULL;
    struct c_container *rv = (struct c_container *)malloc(sizeof(rv->len) + n*sizeof(rv->data));
    rv->len = n;
    return rv;
}

我想使用 BOOST_FOREACH 进行 C++ 风格的迭代,但这不起作用。 (手动调用 range_begin 和 range_end 函数的“旧式”确实有效)。

inline int *range_begin(c_container *c)
{
    return c ? &c->data[0] : NULL;
}
inline int *range_end(c_container *c)
{
    return c ? &c->data[c->len] : NULL;
}
inline const int *range_begin(const c_container *c)
{
    return c ? &c->data[0] : NULL;
}
inline const int *range_end(const c_container *c)
{
    return c ? &c->data[c->len] : NULL;
}

namespace boost
{
    template<>
    struct range_mutable_iterator<c_container *>
    {
        typedef int *type;
    };
    template<>
    struct range_const_iterator<c_container *>
    {
        typedef const int *type;
    };
}

int main()
{
    c_container *coll = make_container(3);
    coll->data[0] = 1;
    coll->data[1] = 42;
    coll->data[2] = -1;

    BOOST_FOREACH(int i, coll)
    {
        std::cout << i << std::endl;
    }
}

根据http://www.boost.org/doc/libs/1_65_1/doc/html/foreach/extensibility.html,这就是应该所必需的一切(我已经用类对其进行了测试)

但是,该示例使用类,而我使用的是指向类的指针。根据我的调查,它似乎正在使用仅适用于 const char *const wchar_t * 的代码路径:

In file included from boost-foreach.cpp:6:0:
/usr/include/boost/foreach.hpp: In function ‘bool boost::foreach_detail_::done(const boost::foreach_detail_::auto_any_base&, const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<T*, C>*) [with T = c_container, C = mpl_::bool_<false>, const boost::foreach_detail_::auto_any_base& = const boost::foreach_detail_::auto_any_base&]’:
boost-foreach.cpp:65:5:   instantiated from here
/usr/include/boost/foreach.hpp:749:57: error: no match for ‘operator!’ in ‘!* boost::foreach_detail_::auto_any_cast [with T = c_container*, C = mpl_::bool_<false>, typename boost::mpl::if_<C, const T, T>::type = c_container*, const boost::foreach_detail_::auto_any_base& = const boost::foreach_detail_::auto_any_base&](((const boost::foreach_detail_::auto_any_base&)((const boost::foreach_detail_::auto_any_base*)cur)))’
/usr/include/boost/foreach.hpp:749:57: note: candidate is: operator!(bool) <built-in>

是否有一些额外的提升特质可以专攻或什么?

【问题讨论】:

    标签: c++ boost boost-foreach


    【解决方案1】:

    似乎很难为 pointer 类型定义范围函数。但是您可以直接为c_container 定义它们。代码如下所示:

    #include <cstdlib>
    #include <iostream>
    #include <boost/foreach.hpp>
    
    struct c_container
    {
        size_t len;
        int data[1];
    };
    
    struct c_container *make_container(size_t n)
    {
        if (n == 0)
            return NULL;
        struct c_container *rv = (struct c_container *)malloc(sizeof(rv->len) + n * sizeof(rv->data));
        rv->len = n;
        return rv;
    }
    
    inline int *range_begin(c_container &c)
    {
        return c.len > 0 ? &c.data[0] : NULL;
    }
    inline int *range_end(c_container &c)
    {
        return c.len > 0 ? &c.data[c.len] : NULL;
    }
    inline const int *range_begin(const c_container &c)
    {
        return c.len > 0 ? &c.data[0] : NULL;
    }
    inline const int *range_end(const c_container &c)
    {
        return c.len > 0 ? &c.data[c.len] : NULL;
    }
    
    namespace boost
    {
        template<>
        struct range_mutable_iterator<c_container>
        {
            typedef int *type;
        };
        template<>
        struct range_const_iterator<c_container>
        {
            typedef const int *type;
        };
    }
    
    #define MY_FOREACH(x, y) BOOST_FOREACH(x, *y)
    
    int main()
    {
        c_container *coll = make_container(3);
        coll->data[0] = 1;
        coll->data[1] = 42;
        coll->data[2] = -1;
    
        //BOOST_FOREACH(int i, *coll)
        MY_FOREACH(int i, coll)
        {
            std::cout << i << std::endl;
        }
    }
    

    注意BOOST_FOREACH 循环 迭代指针类型。作为一种解决方法,您可以定义自己的 FOREACH,如上面的代码所示。

    【讨论】:

    • 如果NULL 代表空容器,这将失败......但我想使用自定义宏我可以将它包装在一个类中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多