从任意映射获取mapped_type的指针或引用

发布于 2024-12-01 21:57:54 字数 3358 浏览 1 评论 0原文

编辑:我已经找到并写下了问题的解决方案,但我没有回答这个问题,因为我的解决方案可能仍然不理想。

我正在编写一个小型库,旨在在地图的地图上执行例程,但是我在设计一组类模板时遇到了麻烦,这些模板将让我获得指向地图的指针或引用(取决于地图的 value_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];
    }

Edit: I've found and written up a solution to my problem but I've left the question unanswered since my solution may still not be ideal.

I'm writing a small library designed to perform routines on maps of maps, but I'm having trouble designing a set of class templates that will let me get a pointer or reference (depending on the second_type of the map's value_type) to a map's mapped_type, regardless of the type of the map (e.g. std::map, boost::ptr_map).

To elaborate further, I have tabulated some input types and desired output types.

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

My code passes cases A, B, D and E, but fails on cases C and F. Here is what I have so far.

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

I'm trying to use boost::mpl to do this, and this is what I've cooked up so far, but I get the same error using both versions of the code.

The error.

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_’

The modified specialization of the struct to deal with l-values that are not pointers to maps.

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];
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

手心的海 2024-12-08 21:57:54

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;
};

C and F seems wrong, the mapped type isn't boost::ptr_map. Otherwise it sounds like you could just use full template specialization to decide whether it is an std::map or boost::ptr_map. Something like this:

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;
};
终遇你 2024-12-08 21:57:54

我已经成功编译了代码,并在过程中大大简化了它,通过使用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];
}

只有方法的主体需要在上面问题中定义的结构的专门版本中进行更改,以便适应以及指向地图的指针。如果您想要完整的代码清单,请告诉我,我会将整个代码转储在这里。

I've got the code the compile successfully and greatly simplified it in the process, by using the mapped_type typedef like so:

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

Only the body of the methods needs to be changed in specialized versions of the struct defined in the question above in order to accommodate for pointers to maps as well. If you would like the entire code listing, let me know and I'll dump the entire thing here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文