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

Other considerations and tips

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 39. Boost.Typeof

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

Other considerations and tips

Native typeof support and emulation

Многие компиляторы уже поддерживают тип GCC и Metrowerks.

Игорь Чесноков открыл метод, позволяющий реализовать<typeof>на VC-серии компиляторов. Он использует ошибку в компиляторе Microsoft, которая позволяет определить вложенный класс базы в классе, полученном из базы:

template<int ID> struct typeof_access
{
    struct id2type; //not defined
};
template<class T, int ID> struct typeof_register : typeof_access
{
    // define base's nested class here
    struct typeof_access::id2type
    {
        typedef T type;
    };
};
//Type registration function 
typeof_register<T, compile-time-constant> register_type(const T&);
//Actually register type by instantiating typeof_register for the correct type
sizeof(register_type(some-type));
//Use the base class to access the type.
typedef typeof_access::id2type::type type;

Педер Холт адаптировал этот метод к VC7.0, где вложенный класс является шаблонным классом, который специализируется на производном классе.

В VC8.0 казалось, что все баги были исправлены, но Стивену Ватанабе удалось внедрить более строгую версию исправления VC7.0, которая позволяет поддерживать «тип» и здесь.

Для многих других компиляторов ни встроенная поддержка<typeof>, ни описанный выше трюк не являются вариантом. Для таких компиляторов метод эмуляции является единственным способом реализации<typeof>.

По приблизительным оценкам, на момент написания этой статьи введение стандарта<typeof>,<auto>и т.д. в стандарт C++ может произойти не скоро. Даже после того, как это будет сделано, пройдет некоторое время, прежде чем большинство компиляторов реализуют эту функцию. Но даже после этого всегда есть устаревшие компиляторы для поддержки (например, сейчас, в 2005 году, многие люди все еще используют VC6, долго после того, как VC7.x и даже бета-версия VC8.0 стали доступны).

Учитывая чрезвычайную полезность функции прямо сейчас, кажется, имеет смысл реализовать ее на библиотечном уровне.

Режим эмуляции кажется важным, даже если на каком-то конкретном компиляторе присутствует лучший вариант. Если автор библиотеки хочет разработать переносной код с использованием<typeof>, ей необходимо использовать режим эмуляции и зарегистрировать свои типы и шаблоны. Те пользователи, у которых есть лучший вариант, все равно могут воспользоваться им, поскольку макросы регистрации определяются как no-op на таких компиляторах, в то время как пользователи, для которых эмуляция является единственным вариантом, будут использовать его.

Другое соображение касается пользователей VC7.1. Несмотря на то, что более удобный трюк<typeof>доступен, следует рассмотреть возможность обновления до VC8, где эмуляция остается единственным вариантом.

Режим эмуляции может быть наложен на компиляторы, которые не используют его по умолчанию, определяя символ<BOOST_TYPEOF_COMPLIANT>:

g++ -D BOOST_TYPEOF_COMPLIANT -I \boost\boost_1_32_0 main.cpp

The three participating parties

Пример Lambda из раздела «Мотивация» требует следующей регистрации:

#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::tuples::tuple, 2);
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor, 1);
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor_base, 2);
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::relational_action, 1);
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::logical_action, 1);
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::other_action, 1);
BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::greater_action);
BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::less_action);
BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::and_action);
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::placeholder, (int));

Может показаться, что цена за возможность обнаружить тип выражения слишком высока: требуется довольно большой объем регистрации. Однако обратите внимание, что вся вышеупомянутая регистрация производится только один раз, и после этого будет обработана любая комбинация зарегистрированных типов и шаблонов. Более того, эта регистрация обычно выполняется не конечным пользователем, а слоем поверх какой-либо библиотеки (в этом примере — Boost.Lambda).

Размышляя об этом, полезно рассмотреть три стороны: тип объекта, библиотеку (вероятно, построенную на принципе шаблонов выражения) и конечного пользователя. Тип объекта отвечает за регистрацию основных типов. Библиотека может регистрировать собственные типы и шаблоны.

В лучшем случае, если выражения всегда состоят только из фундаментальных типов и определяемых библиотекой типов и шаблонов, автор библиотеки может создать впечатление, что<typeof>изначально поддерживается для ее библиотеки. С другой стороны, чем чаще выражения содержат определяемые пользователем типы, тем больше ответственность возлагается на конечного пользователя, и поэтому тем менее привлекательным становится этот подход.

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

Supported features

Библиотека Typeof предварительно регистрирует основные типы. Для этих типов и для любых других типов/шаблонов, зарегистрированных библиотекой пользователя или конечным пользователем, поддерживается любая комбинация из следующего:

  • указатели;
  • ссылки (кроме верхнего уровня);
  • Конст (кроме топ-уровня);
  • Волатилес (кроме высшего уровня);
  • массивы;
  • Функции, указатели функций и ссылки;
  • указания на функции членов;
  • Указатели для членов данных.

Например, следующего типа:

int& (*)(const volatile char*, double[5], void(*)(short))

Поддерживается сразу и что-то вроде:

void (MyClass::*)(int MyClass::*, MyClass[10]) const

При этом он должен быть зарегистрирован<MyClass>.

Библиотека Typeof также предоставляет регистрационные файлы для большинства классов STL. Эти файлы расположены в подкаталоге std и названы в честь соответствующих заголовков STL. Эти файлы не включены в тип системы и должны быть явно включены пользователем, по мере необходимости:

#include <boost/typeof/std/functional.hpp>
BOOST_AUTO(fun, std::bind2nd(std::less<int>(), 21)); //create named function object for future use.

What needs to be registered?

Можно воспользоваться компилятором при регистрации типов библиотеки Typeof. Несмотря на то, что в настоящее время нет прямой поддержки типа языка, компилятор знает, что такое тип выражения, и дает ошибку, если он сталкивается с выражением, которое не было обработано правильно. В контексте<typeof>это сообщение об ошибке будет содержать подсказки о том, какие типы должны быть зарегистрированы в Библиотеке типов, чтобы<BOOST_TYPEOF>работало.

struct X {};
template<typename A,bool B>
struct Y {};
std::pair<X,Y<int,true> > a;
BOOST_AUTO(a,b);

Следующее сообщение об ошибке от VC7.1

error C2504: 'boost::type_of::'anonymous-namespace'::encode_type_impl<V,Type_Not_Registered_With_Typeof_System>' : base
    class undefined
        with
        [
            V=boost::type_of::'anonymous-namespace'::encode_type_impl<boost::mpl::vector0<boost::mpl::na>,std::pair<X,Y<int,true>>>::V0,
            Type_Not_Registered_With_Typeof_System=X
        ]

Проверяя это сообщение об ошибке, мы видим, что компилятор жалуется на<X>.

BOOST_TYPEOF_REGISTER_TYPE(X); //register X with the typeof system

Перекомпиляция, мы получаем новое сообщение об ошибке от VC7.1

error C2504: 'boost::type_of::'anonymous-namespace'::encode_type_impl<V,Type_Not_Registered_With_Typeof_System>' : base
    class undefined
        with
        [
            V=boost::type_of::'anonymous-namespace'::encode_type_impl<boost::mpl::vector0<boost::mpl::na>,std::pair<X,Y<int,true>>>::V1,
            Type_Not_Registered_With_Typeof_System=Y<int,true>
        ]

Проверяя это сообщение об ошибке, мы видим, что компилятор жалуется<Y<int,true>>. Поскольку<Y>является шаблоном и содержит интегральные константы, мы должны проявлять большую осторожность при регистрации:

BOOST_TYPEOF_REGISTER_TEMPLATE(Y,(typename)(bool)); //register template class Y

Хорошей идеей является поиск точного определения<Y>, когда оно содержит интегральные константы. Для простых классов шаблонов, содержащих только имена типов, можно полагаться исключительно на ошибку компилятора.

Вышеприведенный код теперь компилируется.

Этот метод может быть использован для получения обзора того, какие типы должны быть зарегистрированы для данного проекта для поддержки<typeof>.

Limitations

Вложенные параметры шаблона шаблона не поддерживаются, например:

template<template<template<class> class> class Tpl>
class A; // can't register!

Классы и шаблоны, вложенные в другие шаблоны, также не могут быть зарегистрированы из-за проблемы невоспитанного контекста. Это ограничение наиболее заметно в отношении стандартных итераторов в Dinkumware STL, которые реализованы в виде вложенных классов. Вместо этого инстанциации могут быть зарегистрированы:

BOOST_TYPEOF_REGISTER_TYPE(std::list<int>::const_iterator)

PrevUpHomeNext

Статья Other considerations and tips раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 39. Boost.Typeof может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Chapter 39. Boost.Typeof ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:23:18/0.030477046966553/1