2013-06-04 3 views
1

Скажем, у меня есть шаблон функции, которая устанавливает данные в структуры с помощью указателей на член:Указатели членов или альтернативы?

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).

Чтобы уточнить вопрос (см. Также комментарии в this answer): В реальном коде (считыватель конфигурационных файлов) вызывающий выполняет поиск на карте с первой строкой и фактически не знает, что в настоящее время (используя вторую строку), поскольку параметр указатель-член привязан. Также карта инициализируется один раз и используется для нескольких экземпляров A, поэтому указатели на элементы.

Обратите внимание на тег C++ 03. Поэтому C++ 11 lambdas не являются опцией.

+0

Нет указателя-члена. [Что вы пытаетесь сделать] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? Это ужасно странный способ заполнить класс. – GManNickG

+0

@GManNickG добавил некоторое разъяснение (и я уже сказал в самом вопросе, что знаю, что такого указателя нет ...) – Joe

ответ

1

Не уверен, что я прав. Так же, как вы можете связаться с членами 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);

(у меня нет компилятора под рукой, чтобы проверить это, может потребоваться некоторое подтасовка)

+0

Это, вероятно, ближе всего к тому, что я искал. Однако вы можете сохранить параметр шаблона, поскольку «Тип» и «Класс2» должны быть идентичными. – Joe

Смежные вопросы