Boost logo

Boost :

Subject: Re: [boost] [BOOST_FOREACH] Problem to iterate on a non-copyable container...
From: Chris Glover (c.d.glover_at_[hidden])
Date: 2015-05-20 22:29:34


On Tue, 19 May 2015 at 15:16 nico <nicolas.guillot_at_[hidden]> wrote:

> I'm not sure of the title, because I'm not sure the issue comes from the
> "copyablility" of my container.
> I tryied quite everything but I can't get rid of this error.
>
>
Hi Nico,

You can't do what you are trying to do in C++03. To accomplish it, you
need C++11 move semantics to be able to move the MyContainer out of the Get
function. Even without using BOOST_FOREACH, the following code fails;

GetContainer<int> getter(v, m);
MyContainer<int> c = getter.Get(); // <-- Error.

Here's an example with the necessary changes; I changed the scoped_lock to
a unique_lock and added a move constructor.

template <typename T>
class MyContainer
{
public:
    typedef typename std::vector<T>::iterator iterator;
    typedef typename std::vector<T>::const_iterator const_iterator;

    MyContainer(std::vector<T>& vec, boost::mutex& mutex)
        : m_vector(&vec)
        , m_lock(mutex)
    {}

    MyContainer(MyContainer&& other)
        : m_vector(other.m_vector)
    {
        m_lock = std::move(other.m_lock);
        other.m_vector = nullptr;
    }

    iterator begin() { return m_vector->begin(); }
    const_iterator begin() const { return m_vector->begin(); }
    iterator end() { return m_vector->end(); }
    const_iterator end() const { return m_vector->end(); }

private:

    std::vector<T>* m_vector;
    boost::unique_lock<boost::mutex> m_lock;
};

template <typename T>
struct GetContainer
{
    GetContainer(std::vector<T>& vec, boost::mutex& mutex) :
        m_vector(vec),
        m_mutex(mutex)
    {}

    MyContainer<T> Get()
    {
        return MyContainer<T>(m_vector, m_mutex);
    }

    std::vector<T>& m_vector;
    boost::mutex& m_mutex;
};

Once you have move semantics though, you should have access to
range-based-for, which is also C++11

    for(auto&& i : getter.Get())
    {
        std::cout << i << std::endl;
    }

The above code works, so do you still need BOOST_FOREACH?

-- chris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk