如何使用boost :: variant以"二维方式"定义异构std :: map

Mar*_*cký 9 c++ boost boost-variant boost-mpl c++11

我很乐意得到并建议如何以"二维方式"处理boost :: variant.听起来很奇怪,但让我的代码说更多(希望如此):

我编写了一个名为Parameter的类:

template<typename PARAM_TYPE, typename DATA_TYPE=double>
class Parameter : public quantity<PARAM_TYPE, DATA_TYPE>
{
...
}
Run Code Online (Sandbox Code Playgroud)

上面定义的参数的示例用法:

Parameter<si::length, double> SampleParameter1;
Parameter<si::dimensionless, short> SampleParameter2;
Run Code Online (Sandbox Code Playgroud)

当我试图通过上面的例子解释时,我可以使用boost::units::si::???和不同的数据类型double, short, int等定义几个参数类型.

我的目标是构建一个std::map可以存储任何Parameter类型实例的容器(如上所示).

因此我宣布:

typedef boost::variant<Parameter<si::dimensionless, short>, Parameter<si::length, double> > SupportedParameterTypes;
std::map<int, SupportedParameterTypes> myMapStorage;
Run Code Online (Sandbox Code Playgroud)

这很好用,但有一个很大的缺点我想解决 - 我必须定义参数类型的每一个组合我想支持SupportedParameterTypes上面定义的类型.

我的想法是定义boost :: mpl :: vector,保留我想支持的所有参数类型:

typedef boost::mpl::vector<si::dimensionless, si::length> ParameterTypes;
Run Code Online (Sandbox Code Playgroud)

另一方面,支持所有可能的参数数据类型:

typedef boost::mpl::vector<short, int, float, double> ParameterDataTypes;
Run Code Online (Sandbox Code Playgroud)

我遇到了麻烦:

typedef typename boost::make_variant_over<ParameterTypes>::type ParameterTypeVariants;
typedef typename boost::make_variant_over<ParameterDataTypes>::type ParameterDataVariants;

typedef boost::variant<Parameter<ParameterTypeVariants, ParameterDataVariants> > SupportedParameterTypes;
Run Code Online (Sandbox Code Playgroud)

但是定义boost::variant一些Parameter由其他人定义的东西boost::variant似乎不起作用:o(

问题:如何定义std::map容器,保存Parameter在适当的boost::mpl::vectors中定义的所有类型?

我想请你帮忙解决这个问题.也许根据我写的编码它是不是一个好主意/原则,谁知道.我的目标是通过std :: map灵活存储,以便能够保存我的所有参数,而不会使我的代码模糊不清.寻找智能解决方案当然:o)

非常感谢您对我的问题/请求帮助的任何回复

Jar*_*d42 3

你可以用类似的东西来产生所有的配对

template <typename Seq, typename T1, typename T2>
struct cartesian_parameters_helper;

template <std::size_t...Is, typename T1, typename T2>
struct cartesian_parameters_helper<std::index_sequence<Is...>, T1, T2>
{
    static constexpr std::size_t size1 = std::tuple_size<T1>::value;
    using type = boost::variant<
        Parameter<
            std::tuple_element_t<Is / size1, T1>,
            std::tuple_element_t<Is % size1, T2>
            >...>;
};

template <typename T1, typename T2>
struct cartesian_parameters
{
    using type = typename cartesian_parameters_helper<
        std::make_index_sequence<std::tuple_size<T1>::value
                                 * std::tuple_size<T2>::value>,
        T1, T2>::type;
};
Run Code Online (Sandbox Code Playgroud)

然后将其用作

using SupportedParameterTypes =
    cartesian_parameters<std::tuple<si::dimensionless, si::length>,
                         std::tuple<short, int, float, double>>::type;
Run Code Online (Sandbox Code Playgroud)

演示