dimanche 15 mars 2020

type conversion error when using find() and modify() with boost MultiIndex

For some reason I have a type mis-match between the iterator being returned by a find() and the modify() implementation I'm using to operate on it. My code is here and reproduced verbatim here:

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>

class Placeholder {
    public:
        const uint64_t& getPlaceholderTime( void )  const   { return ph_time; }
        const std::string& getPlaceholderId( void ) const   { return ph_id; }
        void setNewId( std::string& newId ) { ph_id = newId; }
        void setNewTime( uint64_t newTime ) { ph_time = newTime; }

    private:
        mutable uint64_t ph_time;
        std::string ph_id;
};

struct IndexByPlaceholderId { };

typedef boost::multi_index_container<
    Placeholder,
    boost::multi_index::indexed_by
    <boost::multi_index::ordered_non_unique< boost::multi_index::identity<Placeholder> >
    ,boost::multi_index::ordered_non_unique<
        boost::multi_index::const_mem_fun<
            Placeholder,
            const uint64_t&,
            &Placeholder::getPlaceholderTime
        >
    >
    ,boost::multi_index::ordered_non_unique<
        boost::multi_index::tag<IndexByPlaceholderId>,
        boost::multi_index::const_mem_fun<
            Placeholder,
            const std::string&,
            &Placeholder::getPlaceholderId
        >
    >
    >
> currentPlaceholderDatabase;

struct handlePlaceholderTransition {

    handlePlaceholderTransition( std::string& newId, uint64_t newTime )
    : newId_(newId)
    , newTime_(newTime)
    {
        std::cout << "NewId: " << newId << std::endl;
        std::cout << "NewTime: " << newTime << std::endl;
    }

    void operator()(Placeholder& ph)
    {
        ph.setNewId( newId_ );
        ph.setNewTime( newTime_ );
    }

    private:
        std::string newId_;
        uint64_t newTime_;
};

void lambdaHandlePlaceholderTransition( Placeholder& ph, std::string& newId, uint64_t newTime )
{
    ph.setNewId( newId );
    ph.setNewTime( newTime );
}

int main()
{
    static currentPlaceholderDatabase currentDb;

    std::string someString = "something";

    auto result = currentDb.get<IndexByPlaceholderId>().find( someString );
    if( result == currentDb.get<IndexByPlaceholderId>().end() )
    {
        std::cout << "NOT FOUND\n";
    }
    else
    {
        std::string newUpdatedId = "NEW_ID";
        currentDb.modify( result, handlePlaceholderTransition( newUpdatedId, 0 ) );
        /*
        currentDb.modify( result, [](Placeholder& ph) {
            std::cout << "Modifying Placeholder\n";
            std::string newUpdatedId = "NEW_ID";
            lambdaHandlePlaceholderTransition( ph, newUpdatedId, 0 );
        });
        */
        std::cout << "FOUND!!\n";
    }
}

This results in an error where the iterator appears to be wrapped in two additional layers of ordered_index_node template conversion (I'm not sure of the proper language to describe this):

/usr/include/boost/multi_index/ordered_index.hpp:434:8: note: template argument deduction/substitution failed: 
87:80: note: 
cannot convert 'result' (type 
'boost::multi_index::detail::bidir_node_iterator<
    boost::multi_index::detail::ordered_index_node<
        boost::multi_index::detail::index_node_base<
            Placeholder, 
            std::allocator<Placeholder> 
        > 
    > 
>') 

to type '...base_type_of_container...::iterator

{aka 
 boost::multi_index::detail::bidir_node_iterator<
    boost::multi_index::detail::ordered_index_node<
        boost::multi_index::detail::ordered_index_node<
            boost::multi_index::detail::ordered_index_node<
                boost::multi_index::detail::index_node_base<
                    Placeholder, 
                    std::allocator<Placeholder> 
                > 
            > 
        > 
    > 
>}' 

the aka shows these types are similar except for the additional 'levels' of template wrapping. This example is rooted in the example shown in the MultiIndex documentation when comparing modify to replace, so I'm at a loss to explain it.

My questions are:

1.) What is the correct syntax to pass this functor so that it compiles successfully using c++11 and

2.) Could I replace the functor with this lambda that should do the same thing? I've tried replacing the currentDb.modify() line with this code snippet (shown in comments above) but get the same error:

currentDb.modify( result, [](Placeholder& ph) {
    std::cout << "Modifying Placeholder\n";
    std::string newUpdatedId = "NEW_ID";
    lambdaHandlePlaceholderTransition( ph, newUpdatedId, 0 );
});

Aucun commentaire:

Enregistrer un commentaire