Как это работает в boost/pfr?
#include <boost/pfr.hpp>
#include <iostream>
#include <tuple>
struct MyStruct {
int a;
float b;
double c;
};
int main() {
MyStruct s{1, 2.0f, 3.0};
// Получение значения полей по индексу
std::cout << boost::pfr::get<0>(s) << std::endl; // Выводит: 1
std::cout << boost::pfr::get<1>(s) << std::endl; // Выводит: 2.0
std::cout << boost::pfr::get<2>(s) << std::endl; // Выводит: 3.0
// Итерация по полям с использованием std::tuple
boost::pfr::for_each_field(s, [](const auto& field) {
std::cout << field << std::endl;
});
return 0;
}
?
Как примерно это возможно?
Здравствуйте, Shmj, Вы писали:
S>Как это работает в boost/pfr?
S>S>#include <boost/pfr.hpp>
S>#include <iostream>
S>#include <tuple>
S>struct MyStruct {
S> int a;
S> float b;
S> double c;
S>};
S>int main() {
S> MyStruct s{1, 2.0f, 3.0};
S> // Получение значения полей по индексу
S> std::cout << boost::pfr::get<0>(s) << std::endl; // Выводит: 1
S> std::cout << boost::pfr::get<1>(s) << std::endl; // Выводит: 2.0
S> std::cout << boost::pfr::get<2>(s) << std::endl; // Выводит: 3.0
S> // Итерация по полям с использованием std::tuple
S> boost::pfr::for_each_field(s, [](const auto& field) {
S> std::cout << field << std::endl;
S> });
S> return 0;
S>}
S>
S>?
S>Как примерно это возможно?
Несколько лет назад эта тема хайповалась, в сети наверняка остались артфакты того хайпа, и на русском языке в том числе, если не ошибаюсь, Яндекс/Полухин. Погугли по словам "magic get"
Здравствуйте, vopl, Вы писали:
V>Несколько лет назад эта тема хайповалась, в сети наверняка остались артфакты того хайпа, и на русском языке в том числе, если не ошибаюсь, Яндекс/Полухин. Погугли по словам "magic get"
Это вот это:
https://github.com/apolukhin/magic_get
?
Тоже использует boost/pfr.hpp
Мне для любопытства бы какой краткий пример, чтобы без изучения тонны исходников этого pfr.hpp понять как примерно такое удалось сделать.
Здравствуйте, Shmj, Вы писали:
S>Мне для любопытства бы какой краткий пример, чтобы без изучения тонны исходников этого pfr.hpp понять как примерно такое удалось сделать.
https://akrzemi1.wordpress.com/2020/10/01/reflection-for-aggregates
https://stackoverflow.com/questions/77464428/how-does-boost-pfr-get-the-names-of-fields-of-a-struct
Здравствуйте, kov_serg, Вы писали:
_>https://akrzemi1.wordpress.com/2020/10/01/reflection-for-aggregates
_>https://stackoverflow.com/questions/77464428/how-does-boost-pfr-get-the-names-of-fields-of-a-struct
Во, спасибо. Получается такой код:
#include <iostream>
#include <string>
#include <tuple>
#include <type_traits>
struct init
{
template <typename T> operator T(); // never defined
};
template <unsigned I>
struct tag : tag<I - 1>
{
};
template <>
struct tag<0>
{
};
template <typename T>
constexpr auto size_(tag<4>) -> decltype(T{init{}, init{}, init{}, init{}}, 0u)
{
return 4u;
}
template <typename T>
constexpr auto size_(tag<3>) -> decltype(T{init{}, init{}, init{}}, 0u)
{
return 3u;
}
template <typename T>
constexpr auto size_(tag<2>) -> decltype(T{init{}, init{}}, 0u)
{
return 2u;
}
template <typename T>
constexpr auto size_(tag<1>) -> decltype(T{init{}}, 0u)
{
return 1u;
}
template <typename T>
constexpr auto size_(tag<0>) -> decltype(T{}, 0u)
{
return 0u;
}
template <typename T>
constexpr size_t size()
{
static_assert(std::is_aggregate_v<T>);
return size_<T>(tag<4>{}); // highest supported number
}
template <typename T, typename F>
void for_each_member(T const& v, F f)
{
static_assert(std::is_aggregate_v<T>);
if constexpr (size<T>() == 4u)
{
const auto& [m0, m1, m2, m3] = v;
f(m0); f(m1); f(m2); f(m3);
}
else if constexpr (size<T>() == 3u)
{
const auto& [m0, m1, m2] = v;
f(m0); f(m1); f(m2);
}
else if constexpr (size<T>() == 2u)
{
const auto& [m0, m1] = v;
f(m0); f(m1);
}
else if constexpr (size<T>() == 1u)
{
const auto& [m0] = v;
f(m0);
}
}
struct Record
{
std::string name;
int age;
double salary;
};
struct Point
{
int x;
int y;
};
int main()
{
Point pt{2, 3};
Record rec {"Baggins", 111, 999.99};
auto print = [](auto const& member)
{
std::cout << member << " ";
};
for_each_member(rec, print);
std::cout << '\n';
for_each_member(pt, print);
std::cout << '\n';
}
И основа всего — т.н. structured binding — или структурное связывание. Я даже не слышал о таком в контексте C++.
const auto& [m0, m1, m2, m3] = v;
Весьма.