2015-12-14 14 views
9

Ich würde mich freuen, zu erfahren, wie man mit boost :: variant auf "zweidimensionale Weise" umgeht. Klingt seltsam, aber mein Code sagen mehr (hoffentlich) lassen:Wie man heterogene std :: map mit boost :: variant in "zweidimensionaler Weise" definiert

ich eine Klasse namens Parameter codiert haben:

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

Beispiel für die Verwendung meines Parameter wie oben definiert:

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

Als ich versuchte, um anhand des obigen Beispiels zu erklären, kann ich mehrere Parametertypen unter Verwendung des boost::units::si::??? und eines anderen Datentyps wie double, short, int usw. definieren.

M y Ziel ist es, einen std::map Container zu konstruieren, der Instanzen eines beliebigen Typs Parameter (wie oben abgetastet) speichern kann.

Deshalb habe ich erklärt:

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

Das funktioniert ziemlich gut, aber einen großen Nachteil haben möchte ich lösen - ich habe jede einzelne Kombination von Parametertyp zu definieren, möchte ich in SupportedParameterTypes Art unterstützen, wie oben definiert.

Meine Idee war, boost :: mpl :: vector constaining alle Parametertypen zu definieren, würde Ich mag unterstützen:

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

Und alle möglichen Parameterdatentypen werden auf der anderen Seite unterstützt:

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

Es kommt meine Probleme:

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; 

Aberdefinierenvon etwas (Parameter), die von einem anderen boost::variant defineed wird, scheint nicht zu funktionieren: o (

FRAGE: Wie std::map Behälter zu definieren, halten alle meine Parameter Arten in geeigneten boost::mpl::vector s definiert?

Ich möchte Sie bitten, dieses Problem zu lösen. Vielleicht ist es keine gute Idee/Prinzip überhaupt, es zu kodieren, wie ich schrieb, wer weiß. Mein Ziel ist es, durch std :: map einen flexiblen Speicher zu haben, um alle meine Parameter zu halten, ohne dass mein Code mehrdeutig ist.Suche nach intelligenter Lösung natürlich: o)

Vielen Dank im Voraus für jede Antwort auf meine Frage/Bitte um Hilfe

+0

warum zwei 'mpl' Vektoren, die Separ ate 'si' Typen und' data' Typen (die Beziehung zwischen ihnen nicht so offensichtlich) sind besser als etwas Einfaches wie 'boost :: variant , Parameter > '? –

+0

Der Grund, warum ich die beiden Typen getrennt benötige, ist, dass jeder Parametertyp mit jedem Datentyp gepaart werden kann. Es gibt ungefähr 20 si :: Typen und ungefähr 4 Daten. Das würde eine große Menge an Kombinationen erzeugen, die ich gerne vermeiden würde. Wie auch immer, danke für deine Antwort! –

Antwort

3

Sie produzieren können alle Ihre Paarung mit so etwas wie

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

Und dann verwenden als

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

Demo

+0

Ich versuche, meine Sachen mit diesem Vorschlag zu implementieren, aber es scheint C++ 14 spezifisch zu sein - zumindest finde ich nicht std :: index_sequence <> gültig für C++ 11. Gibt es eine Analogie für C++ 11? Zum Beispiel in der Boost-Bibliothek? Vielen Dank im Voraus ... –

+0

Es gibt mehrere Implementierungen von 'index_sequence' und' make_index_sequence' auf SO. – Jarod42