Путаница в отношении std :: transform - преобразование std :: map's value_type :: second в std :: vector - PullRequest
1 голос
/ 21 марта 2012

Привет, может кто-нибудь сказать мне, почему VS2010 выдает мне ошибку с этим кодом, я не вижу, в чем проблема с ним?

Код ошибки: ошибка C2679: бинарный '=': не найден оператор, которыйпринимает правый операнд типа 'std :: vector <_Ty>' (или нет приемлемого преобразования)

// 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>() );

Все, что я пытаюсь сделать, это

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

В ответ на Пабло я попытался создать собственный итератор, который принимает массив ElementArray, но теперь я получаю множество ошибок.

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 ]

1 голос
/ 21 марта 2012

Вы можете рассмотреть использование функтора, который может добавлять элементы в целевой массив вместе с std::for_each для обхода карты:

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));
1 голос
/ 21 марта 2012

Проблема ElementsMap::value_type::second_type в ElementArray.То есть вы пытаетесь вставить экземпляры ElementArray в ElementArray, который действительно содержит экземпляры CFVFElementPtr.

Обновление : изменение вашего объявления operator=от

this_type& operator = (typename const_reference value)

до

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

почти работает.За исключением того, что ни VS 2010, ни GCC 4.6.1 не обеспечивают перегрузку vector::insert, которая возвращает итератор.Вам, вероятно, понадобится более новый компилятор, если вы хотите, чтобы ваша ранжированная вставка возвращала итератор для замены iter.

Изменение реализации для вставки всегда в конце, а именно

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

в operator= прекрасно компилируется с GCC 4.6.1 (и, конечно, вы можете удалить все ссылки на iter в вашем классе итераторов).

0 голосов
/ 21 марта 2012

Я нашел ответ, проблема была с моим пользовательским итератором. Правильный, который работает, это

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);
}

Однако я должен предупредить, что если вы используете это в Visual Studio 2010, вам придется реализовать SGI-форму std :: transform. Версия, которая поставляется с VS2010 по какой-то причине, выдает многочисленные ошибки, все из которых лежат в заголовке <xutility>.

Этот std :: transform отлично работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...