如何解压在 mixins Host class 中传递的一组元组(最终转发给 mixins)
how to unpack a set of tuples passed in a mixins Host class (which ultimately are fowarded to the mixins)
我有以下代码,可以很好地将各种 std::tuples
转发到我的 "BaseSensor" 主机 class.
的各种 mixins
#include <iostream> // std::cout std::endl
#include <string> // std::string
#include <map> // std::map
#include <tuple> // 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 , std::tuple<size_t , double > && tp)
{
cout << "TrendSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " << std::get<1>(tp) << endl;
}
};
typedef struct{ double trough; double peak; } Edges;
class EdgeSensor //mixin for BaseSensor
{
public:
EdgeSensor( BaseSensorData * bsd , std::tuple<size_t , double > && tp)
{
cout << "EdgeSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " << std::get<1>(tp) << endl;
}
};
class CO2Threshold// : public ThresholdData
{
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// : public ThresholdData
{
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
, std::tuple<size_t , double , double , double , double> && tp)
: ThresholdMixin
( std::get<2>(tp)
, std::get<3>(tp)
, std::get<4>(tp)
)
{
cout << "ThresholdSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " "
<< std::get<1>(tp) << " " << std::get<2>(tp) << " " << std::get<3>(tp) << " " << std::get<4>(tp)
<< endl;
}
};
template<typename ... SensorType>
class BaseSensor : public BaseSensorData , public SensorType ... //to my BaseSensor class
{
size_t windowSize;
public:
template<typename ... Args>
BaseSensor(const string& _sensorName , Args && ... args)
: BaseSensorData(_sensorName)
, SensorType( this , std::forward<Args>(args) )...
, windowSize(0U)
{
std::tuple<Args...> arr[sizeof...(SensorType)] = { args ... }; //line A
/*for (size_t i = 0; i < sizeof...(SensorType); ++i)
{
for (size_t i = 0; i < sizeof...(Args); ++i)
{
// do stuff
}
}*/
cout << "BaseSensor: " << /*_windowSize << " " << */sensorName << " " << endl;
}
};
int main() {
BaseSensor<ThresholdSensor<O2Threshold> , TrendSensor, EdgeSensor>bs
{
string("testSensor")
, std::make_tuple<size_t , double , double , double , double>( 54U , 2.5f , 10000.3f , 400.5f , 200.3f )
, std::make_tuple<size_t , double >( 53U , 6.5f )
, std::make_tuple<size_t , double >( 52U , 3.5f )
};
/*BaseSensor<ThresholdSensor<CO2Threshold> , TrendSensor, EdgeSensor>bs5
{
string("testSensor")
, std::make_tuple<size_t , double , double , double , double>( 54U , 2.5f , 10000.3f , 400.5f , 200.3f )
, std::make_tuple<size_t , double >( 53U , 6.5f )
, std::make_tuple<size_t , double >( 52U , 3.5f )
};*/
//BaseSensor<ThresholdSensor<CO2Threshold> > bs2{string("test"),11U , 12.5f};
//BaseSensor<TrendSensor> bs3{string("test"), 8U , 10.5f};
//BaseSensor<EdgeSensor> bs4{string("test"), 6U , 18.5f};
}
所以在"BaseSensor"中所有mixins(即"SensorTypes ...")的元组通过"Args ..."参数包转发。这工作正常,但我需要在 BaseSensor::BaseSensor()
正文中访问这些元组。然而,这样做的语法让我难以理解。
如何同时扩展SensorType ...
和Args ...
,并根据元组对"args"进行分类?
使用上面的代码,我在 g++ v4.7.1 和启用的 c++11 中得到以下内容:
varcon.cpp:104:64: error: could not convert ‘args#0’ from ‘std::tuple<long unsigned int, double, double, double, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’
varcon.cpp:104:64: error: could not convert ‘args#1’ from ‘std::tuple<long unsigned int, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’
varcon.cpp:104:64: error: could not convert ‘args#2’ from ‘std::tuple<long unsigned int, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’
varcon.cpp:108:59: error: incomplete type ‘std::tuple_size<std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >&>’ used in nested name specifier
您希望通过以下指令获得什么?
std::tuple<Args...> arr[sizeof...(SensorType)] = { args ... };
Args...
包是不同std::tuple
类型的路径;所以你的 arr
是一个元组的数组;所以你必须用一系列元组的元组来喂它。但是 args...
包它只是一组元组,而不是元组的元组。
所以我的 clang++ 的错误
tmp_002-11,14,gcc,clang.cpp:93:64: error: no viable conversion from
'tuple<unsigned long, double, double, double, double>' to
'tuple<std::tuple<unsigned long, double, double, double, double>,
std::tuple<unsigned long, double>, std::tuple<unsigned long, double>,
(no argument), (no argument)>'
我想你可以扔掉数组部分并将 arr
定义为
std::tuple<Args...> arr { args ... };
接下来,如果你想访问单个元素,你可以这样写
std::get<0>(std::get<1>(arr));
其中第一个std::get
(内部的)访问一个元组(args...
之一),第二个std::get
(更外部的)访问一个元素元组(size_t
或 double
)。
我有以下代码,可以很好地将各种 std::tuples
转发到我的 "BaseSensor" 主机 class.
#include <iostream> // std::cout std::endl
#include <string> // std::string
#include <map> // std::map
#include <tuple> // 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 , std::tuple<size_t , double > && tp)
{
cout << "TrendSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " << std::get<1>(tp) << endl;
}
};
typedef struct{ double trough; double peak; } Edges;
class EdgeSensor //mixin for BaseSensor
{
public:
EdgeSensor( BaseSensorData * bsd , std::tuple<size_t , double > && tp)
{
cout << "EdgeSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " << std::get<1>(tp) << endl;
}
};
class CO2Threshold// : public ThresholdData
{
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// : public ThresholdData
{
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
, std::tuple<size_t , double , double , double , double> && tp)
: ThresholdMixin
( std::get<2>(tp)
, std::get<3>(tp)
, std::get<4>(tp)
)
{
cout << "ThresholdSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " "
<< std::get<1>(tp) << " " << std::get<2>(tp) << " " << std::get<3>(tp) << " " << std::get<4>(tp)
<< endl;
}
};
template<typename ... SensorType>
class BaseSensor : public BaseSensorData , public SensorType ... //to my BaseSensor class
{
size_t windowSize;
public:
template<typename ... Args>
BaseSensor(const string& _sensorName , Args && ... args)
: BaseSensorData(_sensorName)
, SensorType( this , std::forward<Args>(args) )...
, windowSize(0U)
{
std::tuple<Args...> arr[sizeof...(SensorType)] = { args ... }; //line A
/*for (size_t i = 0; i < sizeof...(SensorType); ++i)
{
for (size_t i = 0; i < sizeof...(Args); ++i)
{
// do stuff
}
}*/
cout << "BaseSensor: " << /*_windowSize << " " << */sensorName << " " << endl;
}
};
int main() {
BaseSensor<ThresholdSensor<O2Threshold> , TrendSensor, EdgeSensor>bs
{
string("testSensor")
, std::make_tuple<size_t , double , double , double , double>( 54U , 2.5f , 10000.3f , 400.5f , 200.3f )
, std::make_tuple<size_t , double >( 53U , 6.5f )
, std::make_tuple<size_t , double >( 52U , 3.5f )
};
/*BaseSensor<ThresholdSensor<CO2Threshold> , TrendSensor, EdgeSensor>bs5
{
string("testSensor")
, std::make_tuple<size_t , double , double , double , double>( 54U , 2.5f , 10000.3f , 400.5f , 200.3f )
, std::make_tuple<size_t , double >( 53U , 6.5f )
, std::make_tuple<size_t , double >( 52U , 3.5f )
};*/
//BaseSensor<ThresholdSensor<CO2Threshold> > bs2{string("test"),11U , 12.5f};
//BaseSensor<TrendSensor> bs3{string("test"), 8U , 10.5f};
//BaseSensor<EdgeSensor> bs4{string("test"), 6U , 18.5f};
}
所以在"BaseSensor"中所有mixins(即"SensorTypes ...")的元组通过"Args ..."参数包转发。这工作正常,但我需要在 BaseSensor::BaseSensor()
正文中访问这些元组。然而,这样做的语法让我难以理解。
如何同时扩展SensorType ...
和Args ...
,并根据元组对"args"进行分类?
使用上面的代码,我在 g++ v4.7.1 和启用的 c++11 中得到以下内容:
varcon.cpp:104:64: error: could not convert ‘args#0’ from ‘std::tuple<long unsigned int, double, double, double, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’
varcon.cpp:104:64: error: could not convert ‘args#1’ from ‘std::tuple<long unsigned int, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’
varcon.cpp:104:64: error: could not convert ‘args#2’ from ‘std::tuple<long unsigned int, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’
varcon.cpp:108:59: error: incomplete type ‘std::tuple_size<std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >&>’ used in nested name specifier
您希望通过以下指令获得什么?
std::tuple<Args...> arr[sizeof...(SensorType)] = { args ... };
Args...
包是不同std::tuple
类型的路径;所以你的 arr
是一个元组的数组;所以你必须用一系列元组的元组来喂它。但是 args...
包它只是一组元组,而不是元组的元组。
所以我的 clang++ 的错误
tmp_002-11,14,gcc,clang.cpp:93:64: error: no viable conversion from
'tuple<unsigned long, double, double, double, double>' to
'tuple<std::tuple<unsigned long, double, double, double, double>,
std::tuple<unsigned long, double>, std::tuple<unsigned long, double>,
(no argument), (no argument)>'
我想你可以扔掉数组部分并将 arr
定义为
std::tuple<Args...> arr { args ... };
接下来,如果你想访问单个元素,你可以这样写
std::get<0>(std::get<1>(arr));
其中第一个std::get
(内部的)访问一个元组(args...
之一),第二个std::get
(更外部的)访问一个元素元组(size_t
或 double
)。