2

I have a structure as below, Similarly there could multiple structures with multiple fields.

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

Now if I want to print each field of the above struct I need to manually type,

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

As you can see the above stuff is manually and repeated task, Is there any way we can auto genearate the above things. If anyone can provide code template for eclipse then that would be useful.

Arty
  • 14,883
  • 6
  • 36
  • 69
Arun Pal
  • 687
  • 7
  • 28
  • Why can't you create a method and write it once, so that you can print wherever you want later by just calling it ? – Vishaal Shankar Mar 16 '18 at 07:08
  • 2
    Possible duplicate of [Printing values of all fields in a C++ structure](https://stackoverflow.com/questions/2758937/printing-values-of-all-fields-in-a-c-structure) – A. Sarid Mar 16 '18 at 07:26
  • 1
    You might be interested by [magic_get](https://github.com/apolukhin/magic_get). – Jarod42 Mar 16 '18 at 09:13

3 Answers3

1

There exists a way to enumerate and output all fields of any structure/class automatically, but it exists probably starting only from C++20 standard through unpacking operation (e.g. auto [a, b] = obj;). Next code solves your task for any structure, your structure is used as example, for usage example see main() function at the very end of code:

Try it online!

#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));
}

Output:

1
2
c
3.14
Arty
  • 14,883
  • 6
  • 36
  • 69
0

I think you can just create a method in the struct A that prints all the members. Call it wherever you need to print all the data using 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;
    }
};
Vishaal Shankar
  • 1,648
  • 14
  • 26
  • 2
    I just want to avoid that manual work , as I have multiple structure with multiple field. Also I can't change struct as all these struct are in interface of a given library. – Arun Pal Mar 16 '18 at 07:13
  • Okay, i understand what you were looking for now. My Bad ! – Vishaal Shankar Mar 16 '18 at 09:19
  • 1
    Actually after searching a lot what you said is the only option I have left to do. So I created a script which generate that function in every struct. So my work has been done but I'm still waiting If someone has better way. – Arun Pal Mar 16 '18 at 09:57
0

C++ does not natively support reflection nor introspection. You cannot inspect a type and query it for what members or functions it contains. You are pretty much stuck doing it "manually" or using a library that adds reflection (like boost reflect or Qt which also provides a limited version for QObject derived classes).

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70