C ++将键映射到对象

时间:2018-07-10 05:31:42

标签: c++ boost-mpl

嗨,有一个容器,其中的键是类型名,值是boost或std中的对象/实例???

我想要实现的是针对每种数据类型都有一个对象池,当我想要构造该对象时,我只想通过Key来获取。我已经有可用的代码,但是如果我使用更标准的东西,我会更开心。

目前我有这样的代码:

            template<size_t index, size_t counter, typename T0, typename ...T>
            struct PoolBuilderInternal
            {
                typedef typename boost::mpl::insert<
                    typename PoolBuilderInternal<index - 1, counter + 1, T...>::m
                    , boost::mpl::pair<T0, std::integral_constant<size_t, counter> > >::type m;
            };

            template<size_t counter, typename T0, typename ...T>
            struct PoolBuilderInternal<1, counter, T0, T...>
            {
                typedef typename boost::mpl::map<boost::mpl::pair<T0, std::integral_constant<size_t, counter> > > m;
            };

            template<typename ...T>
            struct Pools
            {
                std::tuple<
                    boost::object_pool<T>...> m_pools;
                typedef typename PoolBuilderInternal<sizeof...(T), 0, T...>::m poolType;

                template<typename T>
                boost::object_pool<T>& GetPool()
                {
                    return std::get< boost::mpl::at<poolType, T>::type::value>(m_pools);
                }
            };

            Pools<int, std::string, int64_t> m_pools;
            m_pools.Get<int>();

编辑:我想要的是一张编译时间图。您可以想象一个std :: tuple <>,但是某些索引std :: get <0,1,2> ...却不能通过键(?std :: tuple_map)

访问

2 个答案:

答案 0 :(得分:2)

如果池中的类型是唯一的,请使用c ++ 14 std::get< T >(std::tuple(s))

#include <iostream>
#include <string>
#include <tuple>

struct A
{
    int value = 17;
};

int main()
{
    auto t = std::make_tuple(1, std::string{"Foo"}, 3.14, A{});
    std::cout << "(" << std::get<int>(t) << ", "
              << std::get<std::string>(t)
              << ", " << std::get<double>(t)
              << ", " << std::get<A>(t).value << ")\n";
}

答案 1 :(得分:0)

如果我正确地理解了这个问题(并且不确定我是否知道),那么您真正想要的是某种 class factory ,并且以各种形式,这是众所周知的设计模式,因为它允许工厂的用户构造其构造函数(实际上是类型,在涉及类层次结构时,常常是类型)是未知的或超出其范围的对象。

在此基础上,我谨向您提供以下概念验证代码。请注意,我匆忙将它们放在一起,可能不是最佳选择。我敢肯定,还有更多的可能,包括将参数传递给相关构造函数,并从调用站点传递到make_string()make_foo()(例如factory [t_string] ("My string")。我会在有空的时候研究一下,如果您对此帖子表现出任何兴趣。

好的,这是您的班级工厂。您应该能够将其应用于任何类型,包括增强类型。按照编码,当前需要在将工厂函数(例如make_string)添加到映射时定义任何需要传递给相关对象的参数(这可能不理想)。这些工厂功能也可以是lambda。再次,我将在以后添加。

#include <functional>
#include <unordered_map>
#include <variant>
#include <iostream>

struct Foo
{
    Foo (int x) : x (x) { }
    int x;
};

enum ObjectType { t_string, t_foo }; // ...
using all_possible_types = std::variant <std::string, Foo>;  // ...

static all_possible_types make_string (const std::string& s)
{
    std::cout << "make_string " << s << "\n";
    return all_possible_types (std::string (s));
}

static all_possible_types make_foo (int x)
{
    std::cout << "make_foo " << x << "\n";
    return all_possible_types (Foo (x));
}

// ...                                            

int main()
{
    std::unordered_map <ObjectType, std::function <all_possible_types ()>> factory;

    factory.insert ({t_string, std::bind (make_string, "Initial string value")});
    factory.insert ({t_foo, std::bind (make_foo, 42)});
    // ...

    all_possible_types variant_string = factory [t_string] ();
    std::cout << std::get <std::string> (variant_string) << "\n\n";

    all_possible_types variant_foo = factory [t_foo] ();
    std::cout << std::get <Foo> (variant_foo).x << "\n";
}

输出:

make_string Initial string value
Initial string value

make_foo 42
42

Live demo

正如我所说,现在看起来并不多,但稍后我会加以改善。同时,我建议您看一下它,以使您了解我在这里所做的事情。