我想创建以下类模板:
用户代码示例。这就是我想要尽可能简单的:
//list of sensors with a member for each sensor
typedef struct {
cOneSensor_f A4_temp1 = cOneSensor_f ("A4t1", 0x1234 /*, x, y, ... and some more configuration data*/);
cOneSensor_i B4_speed = cOneSensor_i ("B4s0", 0x2001 /*, x, y, ... and some more configuration data*/);
}Sensor_list_4_s;
//put the list inside a class template to be able to control all of them as a whole,
//but also access each sensor individually
cSensorsList<Sensor_list_4_s> Sensor_list_4( 4 );
//get sensor values
void do_sensors_stuff()
{
//all sensors as a whole
Sensor_list_4.update();
//access each sensor individually
float A4t1 = Sensor_list_4.A4_temp1();
int B4s0 = Sensor_list_4.B4_speed();
}
幕后 它可以根据需要变得复杂。可能是这样的:
class cOneSensor {}
class cOneSensor_f: class cOneSensor {}
class cOneSensor_i: class cOneSensor {}
template <typename T>
class cSensorsList: public T
{
private:
int bus_code;
cOneSensor *sensors_array;
int nSensors;
public:
cSensorsList(int bus_code):bus_code(bus_code)
{
//--- here is what I don't know how to do: get sensor list from typename T
nSensors = 0; //getSensorListSize_from_T(/* T */);
sensors_array = 0;//getSensorListPointer_from_T<T>(/* T */);
// ---
}
void update(void) {
for (int i=0; i<nSensors; i++)
sensors_array[i].update();
}
};
通过这段代码我得到:
cSensorsList
上的成员可以单独访问每个对象。但是我不知道怎么做:
cSensorsList
中,获取模板结构的成员列表,以循环遍历列表中的所有对象以执行某些操作:getSensorListPointer_from_T()
函数。使用
std::tuple
的常规类和一些实用函数可能就是您想要的:
struct Sensor_list_4_s{
cOneSensor_f A4_temp1;
cOneSensor_i B4_speed;
auto as_tuple() const { return std::tie(A4_temp1, B4_speed); }
auto as_tuple() { return std::tie(A4_temp1, B4_speed); }
};
template <typename... Ts>
void update(std::tuple<Ts&...> t)
{
#if __cplusplus >= 201703L // C++17
std::apply([](auto&... sensors){ (sensors.update(), ...); }, t);
#else
std::apply([](auto&... sensors){
std::initializer_list<int> ini{(sensors.update(), 0)...};
static_cast<void>(ini); // Avoid warning for unused variable
();
}, t);
#endif
}
template <typename F, typename... Ts>
void apply_for_each(F f, std::tuple<Ts&...> t)
{
#if __cplusplus >= 201703L // C++17
std::apply([](auto&... sensors){ (f(sensors), ...); }, t);
#else
std::apply([](auto&... sensors){
std::initializer_list<int> ini{f(sensors), 0)...};
static_cast<void>(ini); // Avoid warning for unused variable
();
}, t);
#endif
}
template <typename... Ts>
void update2(std::tuple<Ts&...> t)
{
apply_for_each([](auto& sensor){ sensor.update(); }, t);
}
template <typename T>
void update3(T& t)
{
apply_for_each([](auto& sensor){ sensor.update(); }, t.as_tuple());
}
那么
Sensor_list_4_s list /* = ... */;
update(list.as_tuple());
apply_for_each([](auto& sensor){ sensor.update(); }, list.as_tuple());
update2(list.as_tuple());
update3(list);