Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define heterogenous std::map using boost::variant in "two dimensional manner"

I would be happy to get and advice how to deal with boost::variant in "two dimensional manner". Sounds strange but let my code say more (hopefully):

I have coded a class called Parameter:

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

Example usage of my Parameter as defined above:

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

As I tried to explain by example above, I can define several Parameter types using the boost::units::si::??? and different data type like double, short, int etc.

My GOAL is to construct a std::map container which can store instances of any Parameter type (as sampled above).

Therefore I have declared:

typedef boost::variant<Parameter<si::dimensionless, short>, Parameter<si::length, double> > SupportedParameterTypes;
std::map<int, SupportedParameterTypes> myMapStorage;

This works pretty well but have one big disadvantage I would like to solve - I have to define every single combination of Parameter type I would like to support in SupportedParameterTypes type as defined above.

My idea was to define boost::mpl::vector constaining all the Parameter types I would like to support:

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

And all the possible Parameter data types being supported on the other hand:

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

There comes my troubles:

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;

But to define boost::variant of something (Parameter) which is defineed by some other boost::variant seems not to work :o(

QUESTION: How to define std::map container holding all my Parameter types defined in appropriate boost::mpl::vectors?

I would like to kindly ask you for help solving this issue. Maybe it is not good idea/principle at all to code it as I wrote, who knows. My goal is to have a flexible storage by std::map to be capable to hold all my Parameters without having my code ambiguous. Looking for smart solution of course :o)

Many thanks in advance for any reply to my question / request for help

like image 927
Martin Kopecký Avatar asked Dec 14 '15 09:12

Martin Kopecký


1 Answers

You may produce all your pairing with something like

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

And then use it as

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

Demo

like image 194
Jarod42 Avatar answered Nov 05 '22 02:11

Jarod42