【问题标题】:type conversion error when using find() and modify() with boost MultiIndex将 find() 和 modify() 与 boost MultiIndex 一起使用时出现类型转换错误
【发布时间】:2020-06-27 02:05:55
【问题描述】:

由于某种原因,我在 find() 返回的迭代器和我用来操作它的 modify() 实现之间存在类型不匹配。我的代码是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";
    }
}

这会导致错误,其中迭代器似乎被包裹在两个额外的 ordered_index_node 模板转换层中(我不确定描述这个的正确语言):

/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> 
        > 
    > 
>') 

输入 '...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> 
                > 
            > 
        > 
    > 
>}' 

aka 显示这些类型是相似的,除了模板包装的附加“级别”。这个例子源于MultiIndexdocumentation比较修改和替换时显示的例子,所以我很茫然解释它。

我的问题是:

1.) 传递此函子的正确语法是什么,以便使用 c++11 成功编译 和

2.) 我可以用这个应该做同样事情的 lambda 替换函子吗?我尝试用此代码 sn-p 替换 currentDb.modify() 行(如上面的 cmets 所示),但得到相同的错误:

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

【问题讨论】:

    标签: c++ c++11 boost lambda boost-multi-index


    【解决方案1】:

    问题 1:您的代码的问题是 result 是索引 #2 的迭代器(用 IndexByPlaceholderId 标记的那个),currentdb.modify(...) 期望迭代器索引 #0。您可以将有问题的行重写为:

    currentDb.get<IndexByPlaceholderId>().modify(
        result, handlePlaceholderTransition( newUpdatedId, 0 ) );
    

    修改是通过迭代器所属的相同索引完成的,或者,作为:

    currentDb.modify(
        currentDb.project<0>(result), handlePlaceholderTransition( newUpdatedId, 0 ) );
    

    它使用iterator projectionresult 获取索引#0 迭代器。顺便说一句,为了让您的 sn-p 工作,您必须为 Placeholder 定义 operator&lt;(因为索引 #0 依赖于它)。

    问题 2:是的,你可以使用 lambda,一旦你用迭代器解决了问题,你自己的例子就可以工作:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-28
      • 2019-03-20
      • 2022-11-04
      • 2012-09-03
      • 2011-06-29
      • 2021-11-21
      • 2011-05-27
      • 1970-01-01
      相关资源
      最近更新 更多