Re: метаданные
От: GamerOne Россия  
Дата: 22.10.09 18:43
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>необходимо хранить данные различных типов в некой структуре.

Z>Требование к объекту
Z>1. Хранение различных типов
Z>2. возможность проверки наличия данных
Z>3. возможность добавления данных различного типа

Если кол-во типов данных конечно и кол-во полей в них тоже, то можно сделать примерно так (вроде все 3 требования удовлетворяются):

#include <boost/shared_ptr.hpp>
#include <vector>
#include <iostream>

enum FieldType {eFieldA, eFieldB, eFieldC, eFieldD};

struct BaseS
{
    virtual ~BaseS(){}
    virtual bool HasField(FieldType const ft)const = 0;
};

struct S: public BaseS
{
   int a;
   int b;
   int c;
   
   virtual bool HasField(FieldType const ft)const 
   { 
       return eFieldA  == ft || eFieldB == ft || eFieldC == ft;
   }
};

struct S2: public BaseS
{
   int a;
   int c;
   int d;

   virtual bool HasField(FieldType const ft)const 
   { 
       return eFieldA  == ft || eFieldC == ft || eFieldD == ft;
   }
};

typedef boost::shared_ptr<BaseS> BaseSPtr;

int main(int argc, char* argv[])
{
    std::vector<BaseSPtr> v;
    v.push_back(BaseSPtr(new S()));
    v.push_back(BaseSPtr(new S2()));

    std::cout << "Has v[0] 'c' field? " << (v[0]->HasField(eFieldC)? "yes": "no") << std::endl;
    std::cout << "Has v[0] 'd' field? " << (v[0]->HasField(eFieldD)? "yes": "no") << std::endl;
    std::cout << "Has v[1] 'c' field? " << (v[1]->HasField(eFieldC)? "yes": "no") << std::endl;
    std::cout << "Has v[1] 'd' field? " << (v[1]->HasField(eFieldD)? "yes": "no") << std::endl;

    return 0;
}


Недостаток: при добавлении нового поля нужно не забывать добавлять его в enum.
Re[13]: метаданные
От: Юрий Жмеренецкий ICQ 380412032
Дата: 22.10.09 22:02
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>c boost::optional пока не разбирался. Для чего это чудо вообще ?


boost::optional<T> можно рассматривать как контейнер, который хранит либо значение типа T, либо 'ничего'.

ЮЖ>>Если в качестве параметра этой функции передается ссылка (на объект типа variant), то и возвращает она ссылку на хранимое значение (опционально константную), а не значение. Схематично — так:

ЮЖ>>
ЮЖ>>template<class T, class V>
ЮЖ>>/*const*/ T& boost::get(/*const*/ V& v)
ЮЖ>>

ЮЖ>>При инстанцировании типом 'const timeval&' проиходит формирование ссылки на ссылку (для типа результата), что является ошибкой.

Z>Ну примерно это и я попытался реализовать. Если ссылочный тип параметр, то и вернуть ссылку. Но у меня идет аргументом индекс, а не boost::variant.


boost::get принимает variant, а не индекс.
template <class T> 
T&  // <--- здесь должна быть ссылка
get (PARAMS index) const
{
    //...
    return boost::get<T>(m_map[index]);     // <-- В качестве аргумента - variant
}


При вызове соответственно нужно указывать просто тип, а возвращена будет ссылка на значение.

Z>Как тогда победить ?

Победить что?

Z>Иначе мне придется код для get (c проверкой наличия данных) вставлять в каждый метод

Ты лучше скажи, как при такой сигнатуре:

 uint Params::getUint    (void) const


ты собираешся узнать о том, что значение отсутствует?

С тем же boost::optional будет выглядеть так:

typedef boost::optional<uint> uint_opt;

uint_opt Params::getUint() const
//...
if(uint_opt v = p.getUint())
{
  uint n = *v + 1;
}
else
{
  // значение отсутствует
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.