it-swarm-ru.tech

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

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

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

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

65
salvador p

Если вы читаете повышение :: любую документацию, они предоставляют источник идеи: 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.

78
Crazy Eddie

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

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

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

20
Michael Aaron Safyan

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

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

9
Tony Delroy