1

編集:問題の解決策を見つけて書き留めましたが、解決策がまだ理想的ではない可能性があるため、質問には回答していません。

マップのマップでルーチンを実行するように設計された小さなライブラリを作成していますが、(マップの value_type の second_type に応じて) マップのマップのタイプに関係なく、mapped_type (std::map、boost::ptr_map など)。

さらに詳しく説明するために、いくつかの入力タイプと必要な出力タイプを表にしました。

Case   Input Type                                   Output Type
 A     std::map<int, std::map<int, int> >           std::map<int, int>&
 B     std::map<int, boost::ptr_map<int, int> >     boost::ptr_map<int, int>&
 C     boost::ptr_map<int, std::map<int, int> >     std::map<int, int>* const
 D     std::map<int, std::map<int, int> >*          std::map<int, int>&
 E     std::map<int, boost::ptr_map<int, int> >*    boost::ptr_map<int, int>&
 F     boost::ptr_map<int, std::map<int, int> >*    std::map<int, int>* const

私のコードは、ケース A、B、D、E には合格しますが、ケース C と F には失敗します。

template <class Map>
struct map_utils
{
    template <class K>
    static typename
    boost::remove_pointer<
            typename Map::value_type
    >::type::second_type&
    get(Map& m, const K k)
    {
            return m[k];
    }

    template <class K>
    static typename
    boost::remove_pointer<
            typename Map::value_type
    >::type::second_type&
    get(const Map& m, const K k)
    {
            return const_cast<Map&>(m)[k];
    }
};

template <class Map>
struct map_utils<Map*>
{
    template <class T>
    static typename
    boost::remove_pointer<
            typename Map::value_type
    >::type::second_type&
    get(Map* m, const T t)
    {
            return (*m)[t];
    }

    template <class T>
    static typename
    boost::remove_pointer<
            typename Map::value_type
    >::type::second_type&
    get(const Map* m, const T t)
    {
            return const_cast<Map*>(m)->operator[](t);
    }
};

これを行うためにboost::mplを使用しようとしています。これはこれまでに作成したものですが、両方のバージョンのコードを使用して同じエラーが発生します。

エラー。

error: invalid initialization of reference of type ‘std::map<int, double>* const&’ from         expression of type     ‘boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::map_config<std::map<int, double>, std::map<int, void*, std::less<int>, std::allocator<std::pair<const int, void*> > >, true>, boost::heap_clone_allocator>::Ty_’

マップへのポインターではない左辺値を処理するための構造体の変更された特殊化。

template <class K>
    static typename
    boost::mpl::if_<
            boost::is_pointer<
                    typename boost::remove_pointer<
                            typename Map::value_type
                    >::type::second_type
            >,
            typename boost::remove_pointer<
                    typename boost::remove_const<
                            typename Map::value_type
                    >::type
            >::type::second_type,
            typename boost::remove_pointer<
                    typename Map::value_type
            >::type::second_type&
    >::type
    get(Map& m, const K k)
    {
            return m[k];
    }
4

2 に答える 2

1

C と F は間違っているようです。マップされた型は boost::ptr_map ではありません。それ以外の場合は、完全なテンプレートの特殊化を使用して、それが std::map または boost::ptr_map であるかどうかを判断できるように思えます。このようなもの:

template <class Map>
class Whatever;

template <class K, class V>
class Whatever<std::map<K, V> >
{
    public:
        typedef V& Type;
};

template <class K, class V>
class Whatever<std::map<K, V>* >
{
    public:
        typedef V& Type;
};

template <class K, class V>
class Whatever<boost::ptr_map<K, V> >
{
    public:
        typedef V* const Type;
};

template <class K, class V>
class Whatever<boost::ptr_map<K, V>* >
{
    public:
        typedef V* const Type;
};
于 2011-08-28T12:41:24.683 に答える
0

次のようにmapped_typetypedefを使用することで、コードを正常にコンパイルし、プロセスで大幅に簡略化できました。

template <class K>
static typename boost::remove_pointer<
        typename Map::mapped_type
>::type&
get(Map& m, const K k)
{
        return m[k];
}

マップへのポインタにも対応するために、上記の質問で定義された構造体の特殊なバージョンでは、メソッドの本体のみを変更する必要があります。コードリスト全体が必要な場合は、お知らせください。ここにすべてをダンプします。

于 2011-08-28T08:31:05.767 に答える