Есть структура и функции:
struct S {
T1 t1;
T2 t2;
// и т.д.
} s;
template <class T> f(const T& t, const char* name) { /* что-то */ }
Необходимо, чтобы работал следующий (псевдо)код:
for (поле : поля(s))
f(поле.значение, поле.имя);
То есть, надо как-то перечислить все поля структуры, получая их тип, значение и имя в виде строки.
Я знаю, что рефлексии в языке C++ нет. Но здесь не нужна рефлексия при выполнении, нужна рефлексия на стадии компиляции или линковки. При этом можно как угодно извращаться с объявлением структуры S
, но нельзя трогать функцию f
. Но в итоге всё равно должна быть каким-либо образом создана либо структура либо что-то структурообразное, поволяющее обращаться к полям (s.t1
и т.д.).
Сторонние библиотеки использовать нельзя, но можно использовать макросы, шаблоны и вообще все доступные возможности C++14.
Как предложил в комментариях к вопросу @KoVadim, можно использовать так называемые X Macro. С их использованием Ваша задача решается примерно следующим образом:
#include <iostream>
#define STRUCT_FIELDS \
X(int, i) \
X(float, f) \
X(const char*, c)
struct S {
#define X(type, name) type name;
STRUCT_FIELDS
#undef X
};
template<typename T> f(const T& t, const char* name)
{
std::cout << name << " = " << t << std::endl;
}
void printStruct(const S& s) {
#define X(type, name) f(s.name, #name);
STRUCT_FIELDS
#undef X
}
int main(int argc, char* argv[]) {
S s;
s.i = 1;
s.f = 10.1;
s.c = "s";
printStruct(s);
}
Результат работы программы:
i = 1
f = 10.1
c = s
Можно допилить мое решение. Оно предназначено для разбора параметров командной строки и помещения их в кортеж, к элементам которого можно обращаться по имени. При этом, имена на этапе компиляции заменяются на индексы элементов в кортеже.
Как с этим работать:
Нужно унаследовать класс от opt-parser
#ifndef CONVOPTIONS_H
#define CONVOPTIONS_H
#include "opt-parser/optparser.h"
struct optlist
{
static constexpr auto options=tuple_cat(
OPTPARSER::makeO<std::string>("input"),
OPTPARSER::makeO<std::string>("output")
);
};
class ConvOptions:public OPTPARSER::Options<optlist>
{
public:
ConvOptions(int argc,char** argv);
};
#endif // CONVOPTIONS_H
После чего, можно обращаться к его полям по именам:
ConvOptions opts(argc,argv);
$(opts,"input")
Коллеги, задумался над такой проблемой: как сделать разный статус заказа в один момент времени для разных пользователей?
Есть задача сформировать базу для личных целейИсходные данные более 2000 заданий 5 работников 2 вида оценок: