我想知道如何正确地循环普通旧数据类型的成员,以获取它们的某些类型信息。那就是:
struct my_pod
{
int a;
double b;
};
template<typename POD>
void loopOverPOD()
{
for_each(POD, member) // The magic part
{
// member::type should be for my_pod int, then double
typename member::type i;
// member::size_of should be equal to sizeof(int) then sizeof(double)
// Trivial if we can have member::type information.
int size = member::size_of;
// member::offset_of should be equal to 0, then sizeof(int)
// Trivial if we can have member::size_of information.
int offset = member::offset_of;
}
}
据我所知,在C ++中,如果不对模板进行一些棘手的操作,我们就无法进行简单的类型内省。但是在这里,我找不到具有模板的具体解决方案,即使实际使用宏也是如此。而问题更多的是关于我而不是存在解决方案。 : - )
我不一定要求一个不会打扰的解决方案。
提前致谢。
答案 0 :(得分:4)
您可以使用boost.fusions ADAPT_STRUCT将您的POD转换为序列,然后使用融合for_each将函数对象应用于每个成员。这是非侵入性的,您的POD类型将保持POD。
好处是您甚至可以将ADAPT_STRUCT宏放在与结构定义分开的(header-)文件中,并且只在需要迭代的代码中使用它们。
另一方面,这个宏需要再次提及成员的类型和名称的冗余。我想在某些时候融合将使用C ++ 11特性来摆脱冗余(再次提到类型)。同时,可以创建一个宏来声明struct和ADAP_STRUCT部分。
答案 1 :(得分:0)
C ++没有构造来迭代结构的成员。
但是存在标准类型std::tuple
,您可以使用模板在编译时递归遍历其元素。
答案 2 :(得分:0)
如果您使用的是C ++ 14和更高版本,则可以使用Boost.Precise and Flat Reflection
(https://github.com/apolukhin/magic_get/)来遍历POD,并使用boost::typeindex::type_id_runtime(field)
打印类型:
#include <iostream>
#include <boost/pfr/precise.hpp>
#include <boost/pfr/flat.hpp>
#include <boost/type_index.hpp>
struct my_pod
{
int a;
double b;
};
struct my_struct
{
char c;
my_pod pod;
};
int main() {
my_pod val{1, 2.5};
my_struct var{'a', 1, 2.5};
std::cout << "Flat:\n";
boost::pfr::flat_for_each_field(var, [](const auto& field, std::size_t idx) {
std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << '\n';
});
std::cout << "\nNot Flat:\n";
boost::pfr::for_each_field(var, [](const auto& field, std::size_t idx) {
using namespace boost::pfr::ops;
std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << '\n';
});
}
此示例的输出:
Flat:
0: char; value: a
1: int; value: 1
2: double; value: 2.5
Not Flat:
0: char; value: a
1: my_pod; value: {1, 2.5}
尽管我不确定在这种情况下如何获得补偿...