1
votes

Hi can anyone tell me why VS2010 gives me an error with this code, I can't see what's the problem with it?

Error code : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::vector<_Ty>' (or there is no acceptable conversion)

// Elements container
typedef std::vector<CFVFElementPtr> ElementArray;
typedef std::map<CVertexSemantic::Type, ElementArray> ElementsMap;

// Create an empty array of elements
ElementsMap::value_type::second_type allElements;

// Concatinate each std::vector found within the map
std::transform(m_elementsMap.begin(), m_elementsMap.end(),
std::insert_iterator<ElementArray>(allElements, allElements.end()),
select2nd<ElementsMap::value_type>() );

All I am trying to do is this

for (auto i = m_elementsMap.begin(); i != m_elementsMap.end(); ++i)
{
    const ElementArray& elements = (*i).second;
    allElements.insert(allElements.end(), elements.begin(), elements.end());
}

As a response to Pablo, I tried creating a custom iterator that accepts an array of ElementArray, but I'm now getting a bucket load of errors.

template < class Container >
class container_insert_interator
{
public:
    typedef container_insert_interator<Container> this_type;
    typedef Container container_type;
    typedef typename Container::const_reference const_reference;
    typedef typename Container::value_type valty;

    explicit container_insert_interator (Container& cont, typename   Container::iterator iter) 
            : container(&cont), iter(iter)
    { }

    this_type& operator = (typename const_reference value)
    { 
        iter = container->insert( iter, std::begin(value), std::end(value) );
        ++iter;
        return *this;
    }

    this_type& operator* ()
    { 
       return *this;
    }

    this_type& operator++ ()
    { 
           return *this;
    }

    this_type operator++ (int)
    {
       return *this;
    }

protected:
    Container* container; // pointer to container
    typename Container::iterator iter ; // iterator into container
};
3
Incase anyone is wondering what select2nd is, it just returns the std::pair<T,U>.second of the value_type of a std::map. - Sent1nel

3 Answers

1
votes

The problem is ElementsMap::value_type::second_type is ElementArray. That is, you're trying to insert instances of ElementArray into an ElementArray, which really holds instances of CFVFElementPtr.

Update: Changing your declaration of operator= from

this_type& operator = (typename const_reference value)

to

template<typename OtherContainer>
this_type& operator = ( OtherContainer const& value)

almost works. Except that neither VS 2010 or GCC 4.6.1 provide the vector::insert overload that returns an iterator. You'll probably need a newer compiler if you want your ranged insert to return an iterator to replace iter.

Changing the implementation to always insert at the end, namely

container->insert( container->end(), std::begin(value), std::end(value) );

in operator= compiles fine with GCC 4.6.1 (and, of course, you can remove all references to iter in your iterator class).

1
votes

You might consider using a functor that can append elements to your target array along with std::for_each to walk the map:

struct ElementArray_appender
{
    ElementArray_appender( ElementArray& dest_) : dest(dest_) {
    };

    void operator()( ElementsMap::value_type const& map_item) {
        ElementArray const& vec( map_item.second);

        dest.insert( dest.end(), vec.begin(), vec.end());
    };

private:
    ElementArray& dest;
};



// in whatever function:

std::for_each( m_elementsMap.begin(), m_elementsMap.end(), ElementArray_appender(allElements));
0
votes

I found the answer, the poblem was with my custom iterator. The correct one that works is

template < class Container >
class container_back_insert_interator
{
public:
    typedef container_back_insert_interator<Container> this_type;
    typedef Container container_type;
    typedef typename container_type::const_reference const_reference;
    typedef typename container_type::value_type valty;

    explicit container_back_insert_interator (container_type& cont) 
    : container(&cont)
    { }

    this_type& operator = (const_reference value)
    { 
        container->insert( container->end(), std::begin(value), std::end(value) );
        return *this;
    }

    this_type& operator* ()
    { 
        return *this;
    }

    this_type& operator++ ()
    { 
        return *this;
    }

    this_type operator++ (int)
    {
        return *this;
    }

protected:
    container_type* container; // pointer to container
};

template < class Container >
inline container_back_insert_interator<Container> container_back_inserter(Container& cont)
{
    return container_back_insert_interator<Container>(cont);
}

However, I must warn that if you do use this in Visual Studio 2010 you will have to implement an SGI form of std::transform. The version that ships with VS2010 for some reason throws numerous errors, all of which lie within the <xutility> header.

This std::transform works just fine.