dimanche 25 septembre 2016

c++ variadic template constructor initialization list of members and mixins

I am trying to initialize a variable number of mixins (ThresholdSensor<> , TrendSensor, EdgeSensor) from my host class (BaseSensor) that also happen to require as constructor argument, a member of the host class (BaseSensor::bsd). I fail in both tasks miserably :)

I am using c++11 , gcc 4.7.1 (so no "emplace" for the std::map) and the code is the following:

#include <iostream> // std::cout std::endl
#include <string>   // std::string
#include <map>   // std::map

using namespace std;

struct BaseSensorData
{
    BaseSensorData(const string & _sensorName)
        : sensorName(_sensorName)
    {}

    const string sensorName;
};

class TrendSensor //mixin for BaseSensor
{
    public:
        TrendSensor( BaseSensorData & bsd , size_t _windowSize , const double & _trainRangefactor)
        {
            cout << "TrendSensor: " << _windowSize << " " << bsd.sensorName << " " << _trainRangefactor << endl;
        }
};

typedef struct{ double trough; double peak; } Edges;
class EdgeSensor  //mixin for BaseSensor
{
    public:
        EdgeSensor( BaseSensorData & bsd , size_t _windowSize , const double _rangeFactor)
        {
            cout << "EdgeSensor: " << _windowSize << " " << bsd.sensorName << " " << _rangeFactor << endl;
        }
};

class CO2Threshold //mixin for ThresholdSensor
{
    std::map<std::string , double>thresholds;

    public:
        CO2Threshold( const double & _toxicThres , const double & _zeroThres , const double & )
        {
            thresholds["toxic"] = _toxicThres;
            thresholds["zero"] = _zeroThres;
            cout << "CO2Threshold: " << _toxicThres << " " << thresholds["zero"] << endl;
        }
};
class O2Threshold //mixin for ThresholdSensor
{
    std::map<std::string , double>thresholds;

    public:
        O2Threshold( const double & _toxicThres , const double & _lowThres , const double & _elecChemThres )
        {
            thresholds["toxic"] = _toxicThres;
            thresholds["low"] = _lowThres;
            thresholds["elecchem"] = _elecChemThres;
            cout << "O2Threshold: " << _toxicThres << " " << thresholds["low"] << " " << thresholds["elecchem"] << endl;
        }
};

template<typename ThresholdMixin> //CO2Threshold , O2Threshold , or others ...
class ThresholdSensor : public ThresholdMixin  //mixin for BaseSensor
{
    public:
        ThresholdSensor ( BaseSensorData & bsd
                        , const size_t & _windowSize
                        , const double & _toxicThres)
            : ThresholdMixin
                ( _toxicThres //3x the same arg
                , _toxicThres //just for the sake
                , _toxicThres //of this exercise
                )
        {
            cout << "ThresholdSensor: " << _windowSize << " " << bsd.sensorName << " " << endl;
        }

};

template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
    BaseSensorData bsd;

    public:
        BaseSensor(const string& _sensorName , size_t _windowSize , const double d)
            :
            bsd(_sensorName) //this causes "Wreorder" warning. 
            ,
            SensorType( bsd , _windowSize , d )...
        {
            cout << "BaseSensor: " << _windowSize << " " << bsd.sensorName << " " << endl;
        }

};

int main() {
    BaseSensor<ThresholdSensor<CO2Threshold> , TrendSensor, EdgeSensor> bs{string("test"),60U , 14.5f};
    //BaseSensor<EdgeSensor> bs2;
}

Focusing on BaseSensor , I run the executable with gdb and I realised that there is no way to get the "bsd" member to initialise first. The "SensorType" mixins will be init first. So how can I init the bsd first?

Secondly, going through the execution step by step, I realised that execution steps only into "ThresholdSensor" and never in "TrendSensor" or "EdgeSensor". Why is that? I though all mixins would be evaluated with the ellipsis syntax. Would initializer_list help with the init ordering somehow? Would initializer_list still be the proposed solution if I included the info that ultimately the BaseSensor mixins will have a different number (and type) of arguments and that each mixin will require different values for these arguments.. ?

Thank you in advance for your help

Aucun commentaire:

Enregistrer un commentaire