Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Making a custom type_index

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 38. Boost.TypeIndex 4.1

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Иногда может возникнуть необходимость в создании собственной информационной системы. Это может быть полезно, если вы хотите сохранить больше информации о типах (положение, размер типа, указатели на общие функции ...) или если у вас есть представление о более компактных представлениях типов.

В приведенном ниже примере показано, как можно создать и использовать определенную пользователем информацию типа_info. Пример работает с RTTI и без него.

Рассмотрим ситуацию, когда пользователь использует только эти типы в<typeid()>:

#include <vector>
#include <string>
namespace my_namespace {
class my_class;
struct my_struct;
typedef std::vector<my_class> my_classes;
typedef std::string my_string;
} // namespace my_namespace

В этом случае пользователь может захотеть сэкономить пространство в двоичном коде и создать собственную систему типов. В этом случае<detail::typenum<>>добавляется метафункция. В зависимости от типа ввода T эта функция будет возвращать различные числовые значения.

#include <boost/type_index/type_index_facade.hpp>
namespace my_namespace { namespace detail {
    template <class T> struct typenum;
    template <> struct typenum<void>{       enum {value = 0}; };
    template <> struct typenum<my_class>{   enum {value = 1}; };
    template <> struct typenum<my_struct>{  enum {value = 2}; };
    template <> struct typenum<my_classes>{ enum {value = 3}; };
    template <> struct typenum<my_string>{  enum {value = 4}; };
    // my_typeinfo structure is used to save type number
    struct my_typeinfo {
        const char* const type_;
    };
    const my_typeinfo infos[5] = {
        {"void"}, {"my_class"}, {"my_struct"}, {"my_classes"}, {"my_string"}
    };
    template <class T>
    inline const my_typeinfo& my_typeinfo_construct() {
        return infos[typenum<T>::value];
    }
}} // my_namespace::detail

<my_type_index>— созданный пользователем класс type_index. Если вы сомневаетесь на этом этапе, вы всегда можете взглянуть на файлы<<boost/type_index/ctti_type_index.hpp>>или<<boost/type_index/stl_type_index.hpp>>. Документация для<type_index_facade>также может быть полезной.

См. осуществление<my_type_index>:

namespace my_namespace {
class my_type_index: public boost::typeindex::type_index_facade<my_type_index, detail::my_typeinfo> {
    const detail::my_typeinfo* data_;
public:
    typedef detail::my_typeinfo type_info_t;
    inline my_type_index() BOOST_NOEXCEPT
        : data_(&detail::my_typeinfo_construct<void>())
    {}
    inline my_type_index(const type_info_t& data) BOOST_NOEXCEPT
        : data_(&data)
    {}
    inline const type_info_t&  type_info() const BOOST_NOEXCEPT {
        return *data_;
    }
    inline const char*  raw_name() const BOOST_NOEXCEPT {
        return data_->type_;
    }
    inline std::string  pretty_name() const {
        return data_->type_;
    }
    template <class T>
    inline static my_type_index type_id() BOOST_NOEXCEPT {
        return detail::my_typeinfo_construct<T>();
    }
    template <class T>
    inline static my_type_index type_id_with_cvr() BOOST_NOEXCEPT {
        return detail::my_typeinfo_construct<T>();
    }
    template <class T>
    inline static my_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT;
};
} // namespace my_namespace

Обратите внимание, что в качестве основы мы использовали класс boost::typeindex::type_index_facade. Этот класс заботился обо всех вспомогательных функциях и операторах (сравнение, хеширование, омтрийинг и другие).

Наконец, мы можем использовать класс my_type_index для получения индексов типов:

my_type_index
    cl1 = my_type_index::type_id<my_class>(),
    st1 = my_type_index::type_id<my_struct>(),
    st2 = my_type_index::type_id<my_struct>(),
    vec = my_type_index::type_id<my_classes>()
;
assert(cl1 != st1);
assert(st2 == st1);
assert(vec.pretty_name() == "my_classes");
assert(cl1.pretty_name() == "my_class");

Обычно для того, чтобы предоставить информацию о типе среды выполнения, нам нужно зарегистрировать класс с помощью макроса. Давайте посмотрим, как макрос<MY_TYPEINDEX_REGISTER_CLASS>может быть реализован для нашего класса<my_type_index>:

namespace my_namespace { namespace detail {
    template <class T>
    inline const my_typeinfo& my_typeinfo_construct_ref(const T*) {
        return my_typeinfo_construct<T>();
    }
#define MY_TYPEINDEX_REGISTER_CLASS                                             \
    virtual const my_namespace::detail::my_typeinfo& type_id_runtime() const {  \
        return my_namespace::detail::my_typeinfo_construct_ref(this);           \
    }
}} // namespace my_namespace::detail

Теперь, когда у нас есть MY_TYPEINDEX_REGISTER_CLASS, давайте реализуем метод<my_type_index::type_id_runtime>:

namespace my_namespace {
    template <class T>
    my_type_index my_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT {
        // Classes that were marked with `MY_TYPEINDEX_REGISTER_CLASS` will have a
        // `type_id_runtime()` method.
        return variable.type_id_runtime();
    }
}

Рассмотрим ситуацию, когда<my_class>и<my_struct>являются полиморфными классами:

namespace my_namespace {
class my_class {
public:
    MY_TYPEINDEX_REGISTER_CLASS
    virtual ~my_class() {}
};
struct my_struct: public my_class {
    MY_TYPEINDEX_REGISTER_CLASS
};
} // namespace my_namespace

Теперь следующий пример будет компилироваться и работать.

my_struct str;
my_class& reference = str;
assert(my_type_index::type_id<my_struct>() == my_type_index::type_id_runtime(reference));

Существует простой способ заставить<boost::typeindex::type_id>использовать свой собственный класс type_index.

Все, что нам нужно сделать, это просто определить<BOOST_TYPE_INDEX_USER_TYPEINDEX>полный путь к файлу заголовка вашего класса индекса типа:

// BOOST_TYPE_INDEX_USER_TYPEINDEX must be defined *BEFORE* first inclusion of <boost/type_index.hpp>
#define BOOST_TYPE_INDEX_USER_TYPEINDEX <boost/../libs/type_index/examples/user_defined_typeinfo.hpp>
#include <boost/type_index.hpp>

Вам также нужно будет добавить несколько типдефов и макросов в файл заголовка «user_defined_typeinfo.hpp»:

#define BOOST_TYPE_INDEX_REGISTER_CLASS MY_TYPEINDEX_REGISTER_CLASS
namespace boost { namespace typeindex {
    typedef my_namespace::my_type_index type_index;
}}

Вот так! Теперь все глобальные методы и типдефы TypeIndex будут использовать ваш класс:

boost::typeindex::type_index worldwide = boost::typeindex::type_id<my_classes>();
assert(worldwide.pretty_name() == "my_classes");
assert(worldwide == my_type_index::type_id<my_classes>());

PrevUpHomeNext

Статья Making a custom type_index раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 38. Boost.TypeIndex 4.1 может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 38. Boost.TypeIndex 4.1 ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:39:38/0.0075340270996094/0