C++ 模板:从源模板结构体访问成员

问题描述 投票:0回答:1

我想创建以下类模板:

  • 在编译时保存不同类的对象列表。
  • 被要求对函数中的所有成员进行一些计算。
  • 有一个成员可以单独访问列表中的每个对象。
  • 列表和成员可以在编译时创建,不需要动态列表。
  • 用户界面必须简单,因为它会被团队中不同的程序员多次使用,而几乎没有 C++ 经验。
  • 使用C++14标准,gcc编译器。

用户代码示例。这就是我想要尽可能简单的:

//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()
    函数。
c++ templates
1个回答
0
投票

使用

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);
© www.soinside.com 2019 - 2024. All rights reserved.