2

私が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はラムダであり、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)
    );
}
4

3 に答える 3

2

SSCCEの投稿後:次を追加するのを忘れた可能性がありますか?

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

それ以外は、私の環境はC ++ 11より前であるため、ここでコードをコンパイルすることはできませんが、不足しているインクルードを追加し、ラムダを通常の名前付き関数に置き換えることで、コードをコンパイルできました。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()
        )
    );
}

追記:ラムダ関数はsを値で取っているので、引数をsNodeTypeとして受け入れた方が効率的だと思います。const NodeType&

于 2012-04-30T14:53:55.293 に答える
0

暗闇の中での別のショット(これだと思います):decltype(node_comparator)デフォルトで構築可能ではないため、構築中に初期化値(node_comparator自体)を提供する必要がありますopen_set。これはあなたがやろうとしているように見えますが、間違っています: 正しい方法は次のとおりです (モジュロの潜在的なタイプミス、詳細はこちら):

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

ここでラムダ式を使用することによって課せられる冗長性を考えると、node_comparator.

于 2012-04-30T12:56:51.560 に答える
0

文脈がほとんどない中で何が問題なのかを推測しようとすると、楽しい娯楽になりますが、有用な答えが得られる可能性は低くなります。理想的には、問題を示す完全なテストケース (つまり、短いコンパイル可能なプログラム) を提供する必要があります。とにかく、闇の中のショット:NodeType専用のstd::hash特殊化があると言いますが、Boost.MultiIndex はboost::hashデフォルトのハッシュジェネレーターとして使用します。そこを探してみてください。

于 2012-04-30T12:35:25.050 に答える