Confused? Me too... Consider the following
typedef std::map<std::string , double> Thresholds;
class Foo
{
public:
Foo( const double & _toxicThres , const double & _zeroThres )
: thresholds
(
MapInitializer<std::string , double>()
.Add("toxic" , _toxicThres)
.Add("zero" , _zeroThres)
)
private:
Thresholds thresholds;
};
The above works fine and initializes an std::map in the constructor's member initialisation list. Now consider this:
typedef std::map<std::string , double> Thresholds;
struct CommonData
{
Thresholds thresholds;
};
class Foo //a mixin
{
public:
Foo( Thresholds & thresholds , const double & _toxicThres , const double & _zeroThres )
: thresholds
(
MapInitializer<std::string , double>()
.Add("toxic" , _toxicThres)
.Add("zero" , _zeroThres)
)
};
class Bar //another mixin
{
public:
Bar( Thresholds & thresholds , const double & _warningThres , const double & _zeroThres)
: thresholds
(
MapInitializer<std::string , double>()
.Add("warning" , _warningThres)
.Add("zero" , _zeroThres)
)
};
class OtherGasThreshold{/*...*/}; //yet another mixin, etc...
template<typename ThresholdMixin> //Foo , Bar , or others ...
class ThresholdSensor : public ThresholdMixin
{
public:
ThresholdSensor(double val1 , double val2)
: ThresholdMixin(cd.thresholds, val1 , val2)
{}
private:
CommonData cd;
};
Note that the MapIniializer code comes from here, and is
template<class K, class V>
class MapInitializer
{
std::map<K,V> m;
public:
operator std::map<K,V>() const
{
return m;
}
MapInitializer& Add( const K& k, const V& v )
{
m[ k ] = v;
return *this;
}
};
Of course the above would not compile, but is there any way to init the map in ThresholdSensor::CommonData in one of the mixins during constructor init. ie can I pass by reference the map, init it in the mixins constructor?
The base subobjects are constructed before the data members, so generally a base initializer can't use derived data members.
I would just keep it simple and have a normal member function:
struct Foo
{
void Init(Thresholds & thresholds)
{
thresholds.emplace("foo", 1.0);
thresholds.emplace("bar", 1.5);
}
// ...
};
template <typename Mx>
struct Thing : Mx
{
Thresholds thresholds;
Thing() { Mx::Init(thresholds); }
// ^^^^^^^^^^^^^^^^^^^^^
// ...
};
Usage:
Thing<Foo> x;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With