C++: boost::pfr

At work I used this library some days ago and I find it amazingly useful:

Basically, boost::pfr lets you work with the fields of a given struct, as a std::tuple, letting you access the elements through an index representing the position where the field is defined at inside the struct.

boost::pfr has also the benefit of being header-file-only and of not having any dependency with any other boost library, making it easy to install (copying its header files and that’s it) and use it.

Let’s see the example below. Suppose you have a struct Person:

struct Person
{
  std::string first_name;
  std::string last_name;
  int birth_year;
};

With boost::pfr, you can access any member in the struct given an index using a method called get() that is very similar to its std::tuple counterpart:

#include "boost/pfr.hpp"

int main()
{
  Person composer { "Martin", "Gore", 1961};
  
  auto& a = boost::pfr::get<0>(composer); // will return a std::string reference
  auto& b = boost::pfr::get<1>(composer);
  auto& c = boost::pfr::get<2>(composer); // will return a reference to the int field

  std::cout << a << ", " << b << ", " << c << "\n";
  return 0;
}

To get then number of elements in a struct, you have boost::pfr::tuple_size:

int main()
{
  std::cout << boost::pfr::tuple_size<Person>::value << "\n";  // returns 3 for our struct
}

To get the type of a given parameter, you have boost::pfr::tuple_element:

int main()
{
  boost::pfr::tuple_element<0, Person>::type s; 
  return 0;
}

In the example above, I declared a variable s whose type is the same type of the element in the 0-th position in the struct Person (i.e. a std::string).

Use cases:

You could create a generic library to iterate through all the members of any struct and do something with each member (kind of std::for_each [boost::pfr provides a for_each_field function template to do this iteration] or std::visit), for example, printing its values out (see my example below), saving them to disk, deserializing them or populating its values from a library (think of a SQL result set or a JSON object).

On printing a struct values out, boost::pfr already ships with a method called io_fields that does exactly that:

int main()
{
  Person singer { "Dave", "Gahan", 1962 };
  std::cout << boost::pfr::io_fields(singer) << "\n";
}

This prints out “{ Dave, Gahan, 1962 }“.

boost::pfr also ships with a lot of utilities to compare elements from a struct in other or to use any struct as a key on standard library maps and sets.

To learn more about this nice library, visit its documentation: https://apolukhin.github.io/pfr_non_boost/

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s