что-то типа boost::any

Тема в разделе "LANGS.C", создана пользователем varnie, 14 июн 2008.

  1. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    привет.

    имеется следующий код:
    Код (Text):
    1. struct AbstractProperty
    2. {
    3.     virtual ~AbstractProperty(){};
    4.     virtual void Set(const std::string &value) = 0;
    5. };
    6.  
    7. template <typename T>
    8. class Property : public AbstractProperty
    9. {
    10. public:
    11.       Property(T &value) :_value(value){}
    12.  
    13.       void Set(const std::string &value)
    14.       {
    15.           _value = boost::lexical_cast<T>(value);
    16.       }
    17.  
    18. private:
    19.     T &_value;
    20. };
    21.  
    22. class VariableContainer
    23. {
    24.     typedef boost::shared_ptr<AbstractProperty> PropertyPtr;
    25.     typedef std::map<std::string, PropertyPtr> NameToPropertyMap;
    26. public:
    27.     template <class T>
    28.     void Register(const std::string &name, T &var)
    29.     {
    30.         _map[name] = PropertyPtr(new Property<T>(var));
    31.     }
    32.  
    33.     template <class T>
    34.     void Set(const std::string &name, const std::string &value)
    35.     {
    36.         _map[name]->Set(value);
    37.     }
    38.    
    39.    
    40. private:
    41.     NameToPropertyMap _map;
    42. };
    который, собссно вызывается след. образом:
    Код (Text):
    1. int main() {
    2.     VariableContainer c;
    3.  
    4.     int i(0);
    5.     std::string str("");
    6.  
    7.     c.Register("int", i);
    8.     c.Register("str", str);
    9.  
    10.     c.Set<int>("int", "12");
    11.     c.Set<std::string>("str", "hello");
    12.  
    13.     std::cout << i << std::endl;
    14.     std::cout << str << std::endl;
    15.  
    16.      return 0;
    17. }
    просится дополнить его, чтобы обращаясь к VariableContainer-у, можно было бы не только регить переменные и устанавливать их значения, но и получать их значения.
    короче, Getter просится (чтобы можно было писать "int value = c.Get("int")". не пойму лишь, как его добавить в AbstractProperty, т.к. на этом уровне тип данных Т еще не известен.
    ткните носом, как здесь выкрутиться, плиз.
     
  2. W4FhLF

    W4FhLF New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2006
    Сообщения:
    1.050
    В AbstractProperty никак, ибо шаблонный метод не может быть виртуальным.

    Можно заюзать RTTI и dynamic_cast, но придётся пожертвовать некоторой функциональностью, а именно boost::shared_ptr<AbstractProperty>, т.к. shared_ptr не является полиморфным классом(можешь написать свою обёртку). В общем с учётом всего вышесказанного решение может быть таким:

    Код (Text):
    1. template <typename T>
    2. class Property : public AbstractProperty
    3. {
    4. public:
    5.     Property(T &value) :_value(value){}
    6.  
    7.     void Set(const std::string &value)
    8.     {
    9.         _value = boost::lexical_cast<T>(value);
    10.     }
    11.  
    12.     T Get()
    13.     {
    14.         return _value;
    15.     }
    16.  
    17. private:
    18.     T &_value;
    19. };
    20.  
    21. class VariableContainer
    22. {
    23.     typedef std::map<std::string, AbstractProperty*> NameToPropertyMap;
    24. public:
    25.     template <class T>
    26.     void Register(const std::string &name, T &var)
    27.     {
    28.         _map[name] = new Property<T>(var);
    29.     }
    30.  
    31.     template <class T>
    32.     void Set(const std::string &name, const std::string &value)
    33.     {
    34.         _map[name]->Set(value);
    35.     }
    36.  
    37.     template<class T>
    38.     T Get(const std::string &type)
    39.     {
    40.         if (Property<T>* p = dynamic_cast< Property<T>* >(_map[type]))
    41.             return p->Get();
    42.         else
    43.             return 0;
    44.     }
    45.  
    46.  
    47. private:
    48.     NameToPropertyMap _map;
    49. };
    50.  
    51. int _tmain(int argc, _TCHAR* argv[])
    52. {
    53.     VariableContainer c;
    54.  
    55.     int i(0);
    56.     std::string str("");
    57.  
    58.     c.Register("int", i);
    59.     c.Register("str", str);
    60.  
    61.     c.Set<int>("int", "12");
    62.     c.Set<std::string>("str", "hello");
    63.  
    64.     std::cout << c.Get<int>("int") << std::endl;
    65.     std::cout << c.Get<std::string>("str") << std::endl;
    66.  
    67.     std::cout << i << std::endl;
    68.     std::cout << str << std::endl;
    69.  
    70.     return 0;
    71. }