|  | 
|      | 
|  | 
| Basic UsageBoost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 37. Boost.TypeErasure
  
   | |||||||||
| ![[Note]](/img/note.png) | 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> (поскольку stdint>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 ::
| реклама |