![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Basic UsageBoost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 37. Boost.TypeErasure
|
![]() | Note |
---|---|
Последовательность MPL объединяет несколько концепций. В редких случаях, когда нам нужна только одна концепция, ее не нужно заворачивать в последовательность MPL. |
any<mpl::vector<copy_constructible<>, typeid_<>, relaxed> > x(10); int i = any_cast<int>(x); // i == 10
copy_constructible
— это встроенная концепция, которая позволяет копировать и уничтожать объект. typeid_
предоставляет информацию о типе времени выполнения, чтобы мы могли использовать any_cast
. relaxed
обеспечивает различные полезные по умолчанию. Без расслабленный
, любой
поддерживает точно то, что вы указываете, и ничего больше. В частности, он позволяет по умолчанию строить и присваивать любой
.
Этот пример не очень много делает. x
приблизительно эквивалентно boost::any. Мы можем сделать его более интересным, добавив некоторые операторы, такие как оператор++
и оператор<<
.
any< mpl::vector< copy_constructible<>, typeid_<>, incrementable<>, ostreamable<> > > x(10); ++x; std::cout << x << std::endl; // prints 11
Библиотека предоставляет концепции для большинства операторов C++, но это, очевидно, не охватывает все варианты использования; нам часто нужно определить наши собственные требования. Возьмем элемент push_back
, определенный несколькими контейнерами STL.
BOOST_TYPE_ERASURE_MEMBER((has_push_back), push_back, 1) void append_many(any<has_push_back<void(int)>, _self&> container) { for(int i = 0; i < 10; ++i) container.push_back(i); }
Мы используем макрос BOOST_TYPE_ERASURE_MEMBER
для определения понятия has_push_back
. Второй параметр — название функции члена, а последний макропараметр указывает число аргументов, которое составляет 1
, поскольку push_back
является унарным. При использовании has_push_back
мы должны сообщить ему подпись функции void(int)
. Это означает, что тип, который мы храним в любом, должен иметь член, который выглядит так:
void push_back(int);
Таким образом, мы могли бы назвать append_many
с std
, std, или
::long> (поскольку std
int>long
можно преобразовать в long
::0>std или string
::std::set>>>>.
Также обратите внимание, что append_many
должен работать непосредственно на его аргументе. Он не может сделать копию. Для этого мы используем _self&
в качестве второго аргумента any
. _self
является плейсхолдером
. Используя _self&
, мы указываем, что любой
сохраняет ссылку на внешний объект вместо выделения собственного объекта.
На самом деле здесь есть еще один placeholder
. Второй параметр has_push_back
по умолчанию _self
. Если бы мы хотели определить функцию члена const, нам пришлось бы изменить ее на const _self
, как показано ниже.
BOOST_TYPE_ERASURE_MEMBER((has_empty), empty, 0) bool is_empty(any<has_empty<bool(), const _self>, const _self&> x) { return x.empty(); }
Для бесплатных функций можно использовать макрос BOOST_TYPE_ERASURE_FREE
.
BOOST_TYPE_ERASURE_FREE((has_getline), getline, 2) std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream) { std::vector<std::string> result; std::string tmp; while(getline(stream, tmp)) result.push_back(tmp); return result; }
Использование has_getline
очень похоже на has_push_back
выше. Разница в том, что заполнитель _self
передается в подписи функции вместо отдельного аргумента.
placeholder
не должен быть первым аргументом. Мы могли бы с такой же легкостью сделать второй аргумент.
void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str) { getline(std::cin, str); }
Статья Basic Usage раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 37. Boost.TypeErasure может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Chapter 37. Boost.TypeErasure ::
реклама |