Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-member initialization in constructor initializer list

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?

like image 969
nass Avatar asked Apr 20 '26 20:04

nass


1 Answers

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;
like image 153
Kerrek SB Avatar answered Apr 23 '26 10:04

Kerrek SB



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!