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_type typedef,如下所示:

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 回答