Автоматически генерировать код для печати каждого поля структуры в C++

У меня есть структура, как показано ниже, Точно так же может быть несколько структур с несколькими полями.

struct A
    {
        int a;
        int b;
        char * c;
        float d
    };

Теперь, если я хочу напечатать каждое поле вышеупомянутой структуры, мне нужно набрать вручную,

cout<<A.a<<endl;
cout<<A.b<<endl;
cout<<A.c<<endl;
cout<<A.d<<endl;

Как вы можете видеть вышеописанное, это ручная и повторяющаяся задача. Есть ли способ автоматически генерировать вышеуказанные вещи? Если кто-то может предоставить шаблон кода для затмения, то это было бы полезно.

3 ответа

Существует способ автоматически перечислять и выводить все поля любой структуры / класса, но он существует, вероятно, начиная только со стандарта C ++ 20 посредством операции распаковки (например, auto [a, b] = obj;). Следующий код решает вашу задачу для любой структуры, ваша структура используется в качестве примера, пример использования см. main() функция в самом конце кода:

Попробуйте онлайн!

      #include <iostream>
#include <tuple>
#include <type_traits>

template <auto I>
struct any_type {
    template <class T> constexpr operator T &() const noexcept;
    template <class T> constexpr operator T &&() const noexcept;
};

template <class T, auto... Is>
constexpr auto detect_fields_count(std::index_sequence<Is...>) noexcept {
    if constexpr (requires { T{any_type<Is>{}...}; })
        return sizeof...(Is);
    else
        return detect_fields_count<T>(std::make_index_sequence<sizeof...(Is) - 1>{});
}

template <class T>
constexpr auto fields_count() noexcept {
    return detect_fields_count<T>(std::make_index_sequence<sizeof(T)>{});
}

template <class S>
constexpr auto to_tuple(S & s) noexcept {
    constexpr auto count = fields_count<S>();
    if constexpr (count == 8) {
        auto & [f0, f1, f2, f3, f4, f5, f6, f7] = s;
        return std::tie(f0, f1, f2, f3, f4, f5, f6, f7);
    } else if constexpr (count == 7) {
        auto & [f0, f1, f2, f3, f4, f5, f6] = s;
        return std::tie(f0, f1, f2, f3, f4, f5, f6);
    } else if constexpr (count == 6) {
        auto & [f0, f1, f2, f3, f4, f5] = s;
        return std::tie(f0, f1, f2, f3, f4, f5);
    } else if constexpr (count == 5) {
        auto & [f0, f1, f2, f3, f4] = s;
        return std::tie(f0, f1, f2, f3, f4);
    } else if constexpr (count == 4) {
        auto & [f0, f1, f2, f3] = s;
        return std::tie(f0, f1, f2, f3);
    } else if constexpr (count == 3) {
        auto & [f0, f1, f2] = s;
        return std::tie(f0, f1, f2);
    } else if constexpr (count == 2) {
        auto & [f0, f1] = s;
        return std::tie(f0, f1);
    } else if constexpr (count == 1) {
        auto & [f0] = s;
        return std::tie(f0);
    } else if constexpr (count == 0) {
        return std::tie();
    }
}

struct A {
    int a;
    int b;
    char const * c;
    float d;
};

int main() {
    A a{.a = 1, .b = 2, .c = "c", .d = 3.14};
    std::apply([](auto const &... x) {
        ((std::cout << x << std::endl), ...); }, to_tuple(a));
}

Выход:

      1
2
c
3.14

Я думаю, что вы можете просто создать метод в struct A это печатает всех участников. Называйте это там, где вам нужно распечатать все данные, используя A.PrintInternalData(),

#include<iostream>

struct A
{
    int a;
    int b;
    char * c;
    float d

    void PrintInternalData()
    {
        std::cout<<A.a<<std::endl;
        std::cout<<A.b<<std::endl;
        std::cout<<A.c<<std::endl;
        std::cout<<A.d<<std::endl;
    }
};

C++ изначально не поддерживает ни рефлексию, ни самоанализ. Вы не можете проверить тип и запросить его, какие члены или функции он содержит. Вы в значительной степени застряли, делая это "вручную" или используя библиотеку, которая добавляет отражение (например, Boost Reflect или Qt, которая также предоставляет ограниченную версию для производных классов QObject).

Другие вопросы по тегам