Modern way to access struct fields by name in C++
Asked Answered
L

2

7

I wanted to check if there's an intuitive and easy way to access struct fields by name in modern C++. I am aware that similar questions have been asked and answered, and C++ reflection is a well investigated subject. I've came across libraries like:

But the common point in all these approaches is that, they only allow you to get the total number of fields within the struct or do a certain operation in for_each manner for all the fields of the struct.

Yes, I can obviously check for the specific "name" of the field I'm looking for, by using the for_each functionality provided by these libraries. But I just wanted to check if there is any other trivial/well-know library that already does this. I would like to be able to deal with arbitrary number of nested structs, which is why I'm looking for something out of the box.

As Louis Go indicated, it would be great to have an accessor like:

auto field = namespace::getField<mystruct>("fieldname");
Loiseloiter answered 18/8, 2020 at 10:58 Comment(4)
Maybe post pseudo code to specify "how" you want to access the field? auto field = namespace::getField<mystruct>("fieldname");?Penneypenni
What do you expect to get as a result type? A struct can have fields of different type so you would have to obtain a union, std::variant or std::any. Which one do you want?Cutting
@LouisGo exactly, I've edited my question with your suggestion.Loiseloiter
@J.Schultke with most of the reflection libraries above, user rewrites the struct with some macros anyhow, so I guess std::variant with all the possible types within the struct specified would be OKLoiseloiter
I
1

For simple structs this can now be done with a recent version of Boost PFR in C++20 mode:

#include <boost/pfr.hpp>

#include <iostream>
#include <string>

struct Foo {
  int a;
  float b;
  std::string c;
};

int main() {
  Foo foo {42, 3.1415, "hello world"};
  boost::pfr::for_each_field(foo, [](const auto f, auto i) {
    std::cout << boost::pfr::get_name<i, Foo>() << ": " << f << '\n';
  });
}

After compiling with g++ -std=c++20 -o foo foo.cpp running ./foo will print:

a: 42
b: 3.1415
c: hello world
Infundibuliform answered 17/10, 2023 at 10:42 Comment(0)
E
-3

You can access class members by name using the member access operator. Example:

struct foo {
    int bar;
} instance;

instance.bar = 42; // access by name

If you mean to access a member based on a string variable rather than by compile time identifier, then no. C++ still as of C++20 does not have reflection features necessary to achieve this.

Quite often when programmers want this, what they actually need is an associative container such as std::map.

Epicenter answered 18/8, 2020 at 11:23 Comment(2)
Yes I mean to access member based on a string variable. The purpose is to have a flexible logging mechanism for only certain signals, which is given by the user in runtime, so that we do not need to serialize/log the entire families of nested structs, which are huge.Loiseloiter
I wonder how C++ has such limitation. Maybe using tuple instead of regular struct.Henton

© 2022 - 2024 — McMap. All rights reserved.