【问题标题】:How to define heterogenous std::map using boost::variant in "two dimensional manner"如何以“二维方式”使用 boost::variant 定义异构 std::map
【发布时间】:2015-12-14 09:24:35
【问题描述】:

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

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

template<typename PARAM_TYPE, typename DATA_TYPE=double>
class Parameter : public quantity<PARAM_TYPE, DATA_TYPE>
{
...
}

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

Parameter<si::length, double> SampleParameter1;
Parameter<si::dimensionless, short> SampleParameter2;

正如我试图通过上面的示例解释的那样,我可以使用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;

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

我的想法是定义 boost::mpl::vector 包含我想支持的所有参数类型:

typedef boost::mpl::vector<si::dimensionless, si::length> ParameterTypes;

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

typedef boost::mpl::vector<short, int, float, double> ParameterDataTypes;

我的烦恼来了:

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;

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

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

我想请您帮忙解决这个问题。也许像我写的那样编码它根本不是一个好主意/原则,谁知道呢。我的目标是通过 std::map 进行灵活的存储,以便能够保存我的所有参数,而不会让我的代码模棱两可。当然是在寻找智能解决方案:o)

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

【问题讨论】:

  • 为什么分开 si 类型和 data 类型的两个 mpl 向量(使它们之间的关系不那么明显)比像 boost::variant&lt;Parameter&lt;si::dimensionless, short&gt;, Parameter&lt;si::length, double&gt; &gt; 这样简单的东西更好?
  • 我之所以需要将两种类型分开,是因为任何参数类型都可以与任何数据类型相匹配。大约有 20 种 si:: 类型和大约 4 种数据类型。这会产生大量我想避免的组合。无论如何,谢谢你的回复!

标签: c++ c++11 boost boost-mpl boost-variant


【解决方案1】:

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

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

然后把它当作

using SupportedParameterTypes =
    cartesian_parameters<std::tuple<si::dimensionless, si::length>,
                         std::tuple<short, int, float, double>>::type;

Demo

【讨论】:

  • 我正在尝试使用这个提案来实现我的东西,但它似乎是特定于 C++14 的——至少我找不到对 C++11 有效的 std::index_sequence。 C++11 有什么类比吗?例如在 Boost 库中?非常感谢提前...
  • 在 SO 上有几个 index_sequencemake_index_sequence 的实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
相关资源
最近更新 更多