Re[3]: Контейнер именованных переменных
От: Qbit86 Кипр
Дата: 16.02.08 01:51
Оценка: 2 (1)
Здравствуйте, c_beginner, Вы писали:

_>Рассматривал как вариант, но проблемки следующего плана. В any придется хранить ссылку на переменную, скажем, boost::reference_wrapper<T>.


Я невнимательно прочитал задание. Действительно, мороки много будет.

_>Каким образом я могу определить тип, который удерживает boost::any — используя boost::any_cast, для всех возможных типов переменных контейнера, а это — не решение.


Перебирать не обязательно, см. пример ниже. Можно заглянуть в файл «boost/any.hpp» и действовать по аналогии. Кстати, ваша реализация так же хороша, как и в Бусте. Только они дополнительно спрятали классы реализации (вашим классам AbstractProperty и Property<> соответствуют бустовские placeholder и holder<>). Т. е. вы могли бы скрыть от класса VariableContainer абстрактный и шаблонный классы, предоставив самый обычный. При этом улучшилась бы инкапсуляция, но раздулся бы код. Так что ваш вариант всё таки лучше, чем мой:
#include <boost/any.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/ref.hpp>

#include <cassert>
#include <iostream>
#include <string>
#include <hash_map>
#include <utility>

class Property
{
private:
  class Placeholder {
  public:
    virtual void Set(boost::any a, std::string const& value) const = 0;
    virtual ~Placeholder() {}
  };
  template <typename T> class Holder : public Placeholder {
  public:
    void Set(boost::any a, std::string const& value) const {
      T::type& ref( boost::any_cast<T>(a) );
      ref = boost::lexical_cast<T::type>(value);
    }
  };
public:
  Property() : setter_() {}
  template <typename T> Property(T const& value) : setter_(new Holder<T>), a_(value) {}
  void Set(std::string const& value) { if (setter_) { setter_->Set(a_, value); } }
private:
  boost::any a_;
  boost::shared_ptr<Placeholder> setter_;
};

class VariableContainer
{
public:
  template <typename T>
  void Register(std::string const& name, T& var)
  {
    map_.insert( std::make_pair(name, boost::ref(var)) );
  }
  void Set(const std::string &name, const std::string &value)
  {
    map_[name].Set(value);
  }
private:
  stdext::hash_map<std::string, Property> map_;
};

int main()
{
  VariableContainer c;

  int i(0);
  std::string str("");

  c.Register("int", i);
  c.Register("str", str);

  c.Set("int", "12");
  c.Set("str", "hello");

  std::cout << i << std::endl;
  std::cout << str << std::endl;

  assert(i == 12);
  assert(str == "hello");
  
  return 0;
}


_>virtual ~AbstractProperty() = 0 {};


Оказывается, это нестандартно: «A function declaration cannot provide both a pure-specifier and a definition», пункт 10.4.2. Т. е. определение чисто-виртуальной функции должно быть вынесено из объявления класса. Но все компиляторы такой код поддерживают, потому синтаксическому анализатору это вовсе не сложно, так что я тоже изредка забиваю на Стандарт.
Глаза у меня добрые, но рубашка — смирительная!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.