【问题标题】:Using boost::multi_index_container使用 boost::multi_index_container
【发布时间】:2012-04-30 00:54:52
【问题描述】:

我一直在尝试使用boost::multi_index_container 来解决我遇到的问题。但是,multi_index_container 甚至无法编译声明。错误在 MPL 函数中很深,我不知道错误出在哪里。

boost::multi_index_container<
    NodeType,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>, decltype(node_comparator)>,
        boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>
    >
> open_set(
    boost::make_tuple(node_comparator)
);

在这种情况下,node_comparator 是一个 lambda,NodeType 本身已经有一个 std::hash 特化。这是错误的文本:

1>d:\backups\code\boost_1_47_0\boost\multi_index\detail\node_type.hpp(56): error C2903: 'node_class' : symbol is neither a class template nor a function template
1>          d:\backups\code\boost_1_47_0\boost\mpl\aux_\preprocessed\plain\apply_wrap.hpp(49) : see reference to class template instantiation 'boost::multi_index::detail::index_node_applier::apply<IndexSpecifierIterator,Super>' being compiled
1>          with
1>          [
1>              IndexSpecifierIterator=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>,
1>              Super=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\mpl\aux_\preprocessed\plain\bind.hpp(207) : see reference to class template instantiation 'boost::mpl::apply_wrap2<F,T1,T2>' being compiled
1>          with
1>          [
1>              F=boost::multi_index::detail::index_node_applier,
1>              T1=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>,
1>              T2=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\mpl\aux_\preprocessed\plain\apply_wrap.hpp(49) : see reference to class template instantiation 'boost::mpl::bind2<F,T1,T2>::apply<U1,U2>' being compiled
1>          with
1>          [
1>              F=boost::multi_index::detail::index_node_applier,
1>              T1=boost::mpl::_2,
1>              T2=boost::mpl::_1,
1>              U1=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>,
1>              U2=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\mpl\aux_\preprocessed\plain\apply.hpp(63) : see reference to class template instantiation 'boost::mpl::apply_wrap2<F,T1,T2>' being compiled
1>          with
1>          [
1>              F=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>,
1>              T1=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>,
1>              T2=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\mpl\aux_\preprocessed\plain\reverse_iter_fold_impl.hpp(82) : see reference to class template instantiation 'boost::mpl::apply2<F,T1,T2>' being compiled
1>          with
1>          [
1>              F=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>,
1>              T1=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>>,
1>              T2=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\mpl\reverse_iter_fold.hpp(43) : see reference to class template instantiation 'boost::mpl::aux::reverse_iter_fold_impl<N,First,Last,State,BackwardOp,ForwardOp>' being compiled
1>          with
1>          [
1>              N=2,
1>              First=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,0>,
1>              Last=boost::mpl::v_iter<boost::mpl::vector2<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,2>,
1>              State=boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>,
1>              BackwardOp=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>,
1>              ForwardOp=boost::mpl::protect<boost::mpl::arg<1>>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\multi_index\detail\node_type.hpp(70) : see reference to class template instantiation 'boost::mpl::reverse_iter_fold<Sequence,State,BackwardOp>' being compiled
1>          with
1>          [
1>              Sequence=boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,
1>              State=boost::multi_index::detail::index_node_base<NodeType,std::allocator<NodeType>>,
1>              BackwardOp=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_1>
1>          ]
1>          d:\backups\code\boost_1_47_0\boost\multi_index_container.hpp(75) : see reference to class template instantiation 'boost::multi_index::detail::multi_index_node_type<Value,IndexSpecifierList,Allocator>' being compiled
1>          with
1>          [
1>              Value=NodeType,
1>              IndexSpecifierList=boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>,
1>              Allocator=std::allocator<NodeType>
1>          ]
1>          c:\repo\render\render\sim\simcontext.cpp(264) : see reference to class template instantiation 'boost::multi_index::multi_index_container<Value,IndexSpecifierList>' being compiled
1>          with
1>          [
1>              Value=NodeType,
1>              IndexSpecifierList=boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>,Wide::Sim::`anonymous-namespace'::<lambda8>>,boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>>
1>          ]

关于原因有什么建议吗?

编辑:几乎没有上下文。但对于那些离不开 SSCCE 的人来说,这里有一个 SSCCE:

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>

struct NodeType {
    int x, y, z;
    float g_score;
    NodeType(int ax, int ay, int az) {
        x = ax;
        y = ay;
        z = az;        
    }
    NodeType() {}
    bool operator==(const NodeType& other) const {
        return x == other.x && y == other.y && z == other.z;
    }
};

template<> struct std::hash<NodeType> : public std::unary_function<const NodeType&, std::size_t> {
    std::size_t operator()(const NodeType& node) const {
        return std::hash<int>()(node.x * 100000 + node.y * 1000 + node.z);
    }
};
template<> struct boost::hash<NodeType> : public std::unary_function<const NodeType&, std::size_t> {
    std::size_t operator()(const NodeType& node) const {
        return std::hash<int>()(node.x * 100000 + node.y * 1000 + node.z);
    }
};

int main() {
    auto h = [&](NodeType x) {
        return 5.0f; // details irrelevant
    };    
    auto node_comparator = [&](NodeType lhs, NodeType rhs) {
        return lhs.g_score + h(lhs) < rhs.g_score + h(rhs);
    };
    boost::multi_index_container<
        NodeType,
        boost::multi_index::indexed_by<
            boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>, decltype(node_comparator)>,
            boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>
        >
    > open_set(
        boost::make_tuple(node_comparator)
    );
}

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    在您的 SSCCE 帖子之后:也许您忘记添加以下内容?

    #include <boost/multi_index/ordered_index.hpp>
    #include <boost/multi_index/identity.hpp>
    

    除此之外,我无法在此处编译您的代码,因为我的环境是 C++11 之前的版本,但我确实设法使它工作,添加缺少的包含并用常规命名函数替换 lambdas。请注意,我必须更改 open_set 的构造参数,如另一个答案中所述:

    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/hashed_index.hpp>
    #include <boost/multi_index/ordered_index.hpp>
    #include <boost/multi_index/identity.hpp>
    
    struct NodeType {
        int x, y, z;
        float g_score;
        NodeType(int ax, int ay, int az) {
            x = ax;
            y = ay;
            z = az;        
        }
        NodeType() {}
        bool operator==(const NodeType& other) const {
            return x == other.x && y == other.y && z == other.z;
        }
    };
    
    template<> struct boost::hash<NodeType> : public std::unary_function<const NodeType&,     std::size_t> {
        std::size_t operator()(const NodeType& node) const {
            return boost::hash<int>()(node.x * 100000 + node.y * 1000 + node.z);
        }
    };
    
    double h(NodeType x) {
        return 5.0f;
    }
    
    bool node_comparator(NodeType lhs, NodeType rhs) {
        return lhs.g_score + h(lhs) < rhs.g_score + h(rhs);
    }
    
    int main() {
        typedef boost::multi_index_container<
            NodeType,
            boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<boost::multi_index::identity<NodeType>, bool (*)(NodeType,NodeType)>,
                boost::multi_index::hashed_unique<boost::multi_index::identity<NodeType>>
            >
        > open_set_t;
    
        open_set_t open_set(
            boost::make_tuple(
                boost::make_tuple(
                    boost::multi_index::identity<NodeType>(),
                    &node_comparator
                ),
                open_set_t::nth_index<1>::type::ctor_args()
            )
        );
    }
    

    附加说明:您的 lambda 函数按值采用 NodeTypes,我想如果他们接受他们的参数为 const NodeType&amp;s 会更有效率。

    【讨论】:

      【解决方案2】:

      在如此少的背景下尝试猜测问题出在哪里,虽然是一种有趣的消遣,但会降低获得有用答案的机会。理想情况下,您应该提供一个完整的测试用例(即一个简短的可编译程序)来显示该问题。无论如何,在黑暗中开枪:你说 NodeType 有一个专用的 std::hash 专业化,但 Boost.MultiIndex 使用 boost::hash 作为其默认哈希生成器。试试看那里。

      【讨论】:

      • 几乎没有上下文。但你是对的——我应该发布一个明确的 SSCCE。
      【解决方案3】:

      在黑暗中的另一个镜头(我认为就是这样):由于decltype(node_comparator) 不是默认可构造的,您必须在open_setconstruction 期间提供一个初始化值(node_comparator 本身)。这似乎是你想要做的,但不正确:正确的方法如下(模数潜在的错别字,更多细节here):

      typedef boost::multi_index_container<
        NodeType,
        ...
      > open_set_t;
      
      open_set_t open_set(
        boost::make_tuple(
          boost::make_tuple(
            boost::multi_index::identity<NodeType>(),
            node_comparator
          ),
          open_set_t::nth_index<1>::type::ctor_args()
        )
      );
      

      考虑到此处使用 lambda 表达式所带来的冗长,我认为您最好编写一个使用定义的默认可构造比较器类而不是 node_comparator

      【讨论】:

      • 我不能使用默认构造的比较器类,逻辑需要一些状态。该错误专门指类的实例化,而不是构造函数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 2014-12-02
      • 2013-01-13
      • 2010-12-14
      • 1970-01-01
      • 2021-04-25
      相关资源
      最近更新 更多