c++可变模板构造函数的成员和混合的初始化列表
c++ variadic template constructor initialization list of members and mixins
我试图从我的主机类(BaseSensor
)初始化一个可变数量的mixins (ThresholdSensor<>
, TrendSensor
, EdgeSensor
),这也恰好需要作为构造函数参数,主机类(BaseSensor::bsd
)的成员。我两个任务都失败了。
我使用的是c++11, gcc 4.7.1(所以std::map没有"emplace"),代码如下:
#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;
}
关注BaseSensor
,我用gdb
运行可执行文件,我意识到没有办法让"bsd"成员首先初始化。"SensorType"混合将首先被初始化。那么我如何首先初始化bsd呢?
其次,通过一步一步的执行,我意识到执行步骤只进入"ThresholdSensor",而没有进入"TrendSensor"或"EdgeSensor"。为什么呢?我认为所有的混合将与省略号语法进行评估。initializer_list
会在某种程度上帮助init排序吗?initializer_list
仍然是建议的解决方案,如果我包括的信息,最终basessensor mixins将有不同的数量(和类型)的参数,每个mixin将需要不同的值为这些参数。
提前感谢您的帮助
我不太喜欢下面的解决方案,但是…
第一:你可以修改SensorType
类,接收(作为构造函数的第一个参数)一个指针到BaseSensorData
而不是引用;例如,TendSensor
变成
class TrendSensor //mixin for BaseSensor
{
public:
TrendSensor (BaseSensorData * pBsd, size_t _windowSize,
const double & _trainRangefactor)
{ std::cout << "TrendSensor: " << _windowSize << " "
<< pBsd->sensorName << " " << _trainRangefactor << std::endl; }
};
第二:你可以修改BaseSensor
从BaseSensorData
派生(重要:在SensorType...
包之前),并删除bsd
成员;BaseSensor
成为
template <typename ... SensorType>
class BaseSensor : public BaseSensorData, public SensorType ...
{
public:
BaseSensor (const std::string & _sensorName, size_t _windowSize,
const double d)
: BaseSensorData(_sensorName), SensorType(this, _windowSize, d )...
{ std::cout << "BaseSensor: " << _windowSize << " "
<< sensorName << " " << std::endl; }
};
完整示例如下
#include <iostream> // std::cout std::endl
#include <string> // std::string
#include <map> // std::map
struct BaseSensorData
{
BaseSensorData (const std::string & _sensorName)
: sensorName(_sensorName)
{}
const std::string sensorName;
};
class TrendSensor //mixin for BaseSensor
{
public:
TrendSensor (BaseSensorData * pBsd, size_t _windowSize,
const double & _trainRangefactor)
{ std::cout << "TrendSensor: " << _windowSize << " "
<< pBsd->sensorName << " " << _trainRangefactor << std::endl; }
};
typedef struct { double trough; double peak; } Edges;
class EdgeSensor //mixin for BaseSensor
{
public:
EdgeSensor (BaseSensorData * pBsd, size_t _windowSize,
const double _rangeFactor)
{ std::cout << "EdgeSensor: " << _windowSize << " "
<< pBsd->sensorName << " " << _rangeFactor << std::endl; }
};
class CO2Threshold //mixin for ThresholdSensor
{
private:
std::map<std::string, double> thresholds;
public:
CO2Threshold (const double & _toxicThres, const double & _zeroThres,
const double & )
{
thresholds["toxic"] = _toxicThres;
thresholds["zero"] = _zeroThres;
std::cout << "CO2Threshold: " << _toxicThres << " "
<< thresholds["zero"] << std::endl;
}
};
class O2Threshold //mixin for ThresholdSensor
{
private:
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;
std::cout << "O2Threshold: " << _toxicThres << " "
<< thresholds["low"] << " " << thresholds["elecchem"]
<< std::endl;
}
};
template <typename ThresholdMixin> //CO2Threshold , O2Threshold , or others ...
class ThresholdSensor : public ThresholdMixin //mixin for BaseSensor
{
public:
ThresholdSensor (BaseSensorData * pBsd, const size_t & _windowSize,
const double & _toxicThres)
: ThresholdMixin
( _toxicThres, //3x the same arg
_toxicThres, //just for the sake
_toxicThres) //of this exercise
{ std::cout << "ThresholdSensor: " << _windowSize << " "
<< pBsd->sensorName << " " << std::endl; }
};
template <typename ... SensorType>
class BaseSensor : public BaseSensorData, public SensorType ...
{
public:
BaseSensor (const std::string & _sensorName, size_t _windowSize,
const double d)
: BaseSensorData(_sensorName), SensorType(this, _windowSize, d )...
{ std::cout << "BaseSensor: " << _windowSize << " "
<< sensorName << " " << std::endl; }
};
int main()
{
BaseSensor<ThresholdSensor<CO2Threshold>,
TrendSensor, EdgeSensor> bs { std::string("test"), 60U, 14.5f };
//BaseSensor<EdgeSensor> bs2;
}
相关文章:
- C++成员初始化
- c++构造函数成员初始化:传递参数
- C++正确的指针成员初始化
- 将另一个类的对象传递到当前类C++的构造函数中(不是成员初始化)
- WinLamb 错误:成员初始化非法
- 使用其他成员初始化结构的成员?
- C++模板类静态成员初始化
- 解释了构造函数成员初始化列表
- 如何在成员初始化列表中声明共享指针
- C++入门5版:使用get成员初始化另一个与shared_ptr无关的对象
- C++11 默认类成员初始化与初始值设定项列表同时
- 调用非默认构造函数作为成员初始化
- C++模板成员初始化:用右值移动构造,但用左值移动引用
- 类成员初始化C++
- 在成员初始化列表中,我可以创建对列表中不在列表中的成员变量的引用
- C :(不重复)积分静态成员初始化(不仅是声明!),导致链接器错误,原因
- 如何调用成员初始化器列表中参考成员的构造函数
- C 构造函数采用成员初始化器
- 与其他静态const成员初始化静态常量成员
- 静态内联成员初始化顺序