Как повысить:: вариант и повысить:: любой работы?

Как вариант и любой из библиотеки boost работают внутри? В проекте, над которым я работаю, я использую теговый союз. Я хочу использовать что-то еще, потому что объединения в C++ не позволяют вам использовать объекты с конструкторами, деструкторами или перегруженными операторами присваивания.

Я запросил размер любого и варианта, и провел несколько экспериментов с ними. В моей платформе вариант принимает размер самого длинного из возможных типов плюс 8 байт: я думаю, что это всего лишь 8 байт информации о типе, а остальное - хранимое значение. С другой стороны, любой просто занимает 8 байтов. Так как я на 64-битной платформе, я думаю, что любой просто держит указатель.

Как кто-нибудь знает, какой тип он содержит? Как Variant достигает того, что он делает с помощью шаблонов? Я хотел бы узнать больше об этих классах, прежде чем использовать их.

3 ответа

Решение

Если вы читаете поддержку:: любую документацию, они предоставляют источник идеи: http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf

Это скрытие базовой информации, необходимый навык C++. Узнать его!

Поскольку ответ с наибольшим количеством голосов здесь абсолютно неверен, и я сомневаюсь, что люди на самом деле пойдут посмотреть на источник, чтобы проверить этот факт, вот базовая реализация любого подобного интерфейса, который обернет любой тип функцией f() и позвольте ему называться:

struct f_any
{
   f_any() : ptr() {}
   ~f_any() { delete ptr; }
   bool valid() const { return ptr != 0; }
   void f() { assert(ptr); ptr->f(); }

   struct placeholder
   {
     virtual ~placeholder() {}
     virtual void f() const = 0;
   };

   template < typename T >
   struct impl : placeholder
   {
     impl(T const& t) : val(t) {}
     void f() const { val.f(); }
     T val;
    };
   // ptr can now point to the entire family of 
   // struct types generated from impl<T>
   placeholder * ptr;

   template < typename T >
   f_any(T const& t) : ptr(new impl<T>(t)) {}

  // assignment, etc...
};

boost:: any делает то же самое, за исключением того, что f() на самом деле возвращает typeinfo const& и обеспечивает доступ к другой информации для функции any_cast для работы.

Ключевая разница между boost::any а также boost::variant в том, что any может хранить любой тип, в то время как variant может хранить только один из набора перечислимых типов. any тип магазинов void* указатель на объект, а также typeinfo объект, чтобы запомнить базовый тип и обеспечить некоторую степень безопасности типа. В boost::variant, он вычисляет объект максимального размера и использует "размещение нового" для размещения объекта в этом буфере. Он также хранит тип или индекс типа.

Обратите внимание, что если у вас установлен Boost, вы сможете увидеть исходные файлы в "any.hpp" и "option.hpp". Просто ищите "include/boost/ option.hpp" и "include/boost/any.hpp" в "/usr", "/usr/local" и "/opt/local", пока не найдете установленные заголовки, и Вы можете посмотреть.

редактировать
Как отмечалось в комментариях ниже, в моем описании boost::any была небольшая неточность. Хотя это может быть реализовано с помощью void* (и шаблонный обратный вызов уничтожения для правильного удаления указателя), реализация фактически использует any<T>::placeholder*, с any<T>::holder<T> как подклассы any<T>::placeholder для унификации типа.

boost::any просто снимки typeinfo в то время как шаблонный конструктор работает: у него есть указатель на не шаблонный базовый класс, который обеспечивает доступ к typeinfo, и конструктор получил класс, зависящий от типа, удовлетворяющий этому интерфейсу. Та же самая техника может фактически использоваться, чтобы захватить другие общие возможности набора типов (например, потоковая передача, общие операторы, определенные функции), хотя повышение не предлагает управления этим.

Boost:: вариант концептуально похож на то, что вы делали раньше, но не буквально используя union и вместо этого, применяя ручной подход к размещению / уничтожению объектов в своем буфере (при явной обработке проблем выравнивания), он обходит ограничения, которые в C++ имеют сложные типы в действительности unions.

Другие вопросы по тегам