Скажем, у меня есть шаблонная функция, которая устанавливает данные в структуре через указатели на член:
struct S
{
double d;
unsigned int u;
};
struct A
{
S s, s2;
float f;
int i;
};
template<typename Stream, typename Class, typename Type>
void read(Stream& s, Class& out, Type Class::*member)
{
s >> out.*member;
}
Теперь для постоянных членов, таких как f
а также a
Я могу использовать эту функцию на произвольном экземпляре struct A
:
#include <sstream>
int main(int, char**)
{
std::stringstream stream;
A a;
stream.clear(); stream.str("1");
read(stream, a, &A::i);
stream.clear(); stream.str("1.5");
read(stream, a, &A::f);
stream.clear(); stream.str("2");
printf("%i\n", a.i);
printf("%f\n", a.f);
}
Но есть ли способ получить доступ к членам A::s
или же A::s2
подобным образом без написание новой, эффективно идентичной функции для каждого составного элемента (s
, s2
, так далее.)?
Насколько мне известно, указатели на участников не существуют, но есть ли альтернативное решение? (Это должно работать на произвольных случаях struct
или же class
аналогично тому, как работает решение «указатель на член» выше, и не должно требовать дополнительных методов в A
или же S
).
Чтобы прояснить вопрос несколько (см. Также комментарии в этот ответ): В реальном коде (программа чтения файлов конфигурации) вызывающая сторона выполняет поиск на карте с первой строкой и фактически не знает, что в данный момент читается (используя вторую строку), в качестве указателя на член параметр связан. Также карта инициализируется один раз и используется для нескольких экземпляров A
поэтому указатели на членов.
Обратите внимание на тег c ++ 03. Поэтому лямбды с ++ 11 не вариант.
Не уверен, правильно ли я понял проблему.
Точно так же, как вы можете связаться с членами i, f с PTM, вы можете сделать то же самое с S. Вам не нужна отдельная функция для доступа к s и s2: одиночная функция будет делать с дополнительным аргументом типа S A::*
,
Или, если типы должны быть переменными, вы можете расширить свою функцию чтения примерно так:
template<typename Stream, typename Class, typename Type, typename Class2, typename Type2>
void read(Stream& s, Class& out, Type Class::*member, Type2 Class2::*member2)
{
s >> ((out.*member).*member2);
}
и использовать его как read(stream, a, &A::s, &S::u);
(У меня нет компилятора под рукой, чтобы проверить его, возможно, потребуется доработка)
Других решений пока нет …