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

Generating emptiness and identity

Boost , Chapter 1. The Variadic Macro Data Library 1.9 , Useful variadic macros not in Boost PP

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
Using BOOST_PP_EMPTY and BOOST_PP_IDENTITY

Увеличить PP Имеет макрос под названием BOOST_PP_EMPTY(), который расширяется до нуля.

Обычно это не кажется полезным, но макрос может быть использован в ситуациях, когда требуется вернуть определенное значение, даже если требуется дополнительный синтаксис макровызова без параметров. Этот вид полезности происходит в Boost PP, когда есть два пути, которые нужно пройти в зависимости от результата логики BOOST_PP_IF или BOOST_PP_IIF. Вот искусственный пример:

#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#define MACRO_CHOICE(parameter) \
    BOOST_PP_IIF(parameter) \
        ( \
        MACRO_CALL_IF_PARAMETER_1, \
        SOME_FIXED_VALUE BOOST_PP_EMPTY \
        ) \
    ()
#define MACRO_CALL_IF_PARAMETER_1() some_processing

В общей логике выше: если параметр равен 1, то используется другой макрос, тогда как если параметр равен 0, возвращается некоторое фиксированное значение. Причина, по которой это полезно, заключается в том, что вы можете не захотеть кодировать макрос MACRO_CHOICE таким образом:

#include <boost/preprocessor/control/iif.hpp>
#define MACRO_CHOICE(parameter) \
    BOOST_PP_IIF(parameter) \
        ( \
        MACRO_CALL_IF_PARAMETER_1(), \
        SOME_FIXED_VALUE \
        )
#define MACRO_CALL_IF_PARAMETER_1() some_processing

Потому что это неэффективно. Вызов MACRO_CALL_IF_PARAMETER_1 будет по-прежнему генерироваться, даже если «параметр» равен 0.

Эта идиома возврата фиксированного значения через использование BOOST_PP_EMPTY настолько полезна, что Boost PP имеет сопровождающий макрос к BOOST_PP_EMPTY для работы с ним. Сопровождающим макросом является BOOST_PP_IDENTITY(value)(). По сути, BOOST_PP_IDENTITY возвращает свою ценность при вызове. Опять же, как и в случае с BOOST_PP_EMPTY, окончательное обращение должно быть сделано без какой-либо ценности.

Наш пример сверху, который первоначально использовал BOOST_PP_EMPTY для возврата фиксированного значения, теперь:

#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/facilities/identity.hpp>
#define MACRO_CHOICE(parameter) \
    BOOST_PP_IIF(parameter) \
        ( \
        MACRO_CALL_IF_PARAMETER_1, \
        BOOST_PP_IDENTITY(SOME_FIXED_VALUE) \
        ) \
    ()
#define MACRO_CALL_IF_PARAMETER_1() some_processing

На самом деле BOOST_PP_IDENTITY это:

#define BOOST_PP_IDENTITY(value) value BOOST_PP_EMPTY

Таким образом, вы можете увидеть, что это, по сути, сокращение для обычного случая, первоначально показанного в верхней части возврата значения с помощью BOOST_PP_EMPTY.

Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY

Единственная проблема при использовании BOOST_PP_EMPTY и BOOST_PP_IDENTITY заключается в том, что окончательный вызов должен быть без параметров. Это очень ограничивает. Если окончательный вызов должен быть с одним или несколькими параметрами, вы не можете использовать BOOST_PP_EMPTY или BOOST_PP_IDENTITY. Иными словами, внесение изменений в один из двух примеров:

#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#define MACRO_CHOICE(parameter1,parameter2) \
    BOOST_PP_IIF(parameter1) \
        ( \
        MACRO_CALL_IF_PARAMETER_1, \
        SOME_FIXED_VALUE BOOST_PP_EMPTY \
        ) \
    (parameter2)
#define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_a_parameter

или

#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/facilities/identity.hpp>
#define MACRO_CHOICE(parameter1,parameter2) \
    BOOST_PP_IIF(parameter1) \
        ( \
        MACRO_CALL_IF_PARAMETER_1, \
        BOOST_PP_IDENTITY(SOME_FIXED_VALUE) \
        ) \
    (parameter2)
#define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_a_parameter

Это приведет к ошибке предварительной обработки, поскольку окончательное вызов либо BOOST_PP_EMPTY, либо BOOST_PP_IDENTITY не может быть выполнено с 1 или более параметрами.

Было бы гораздо полезнее, если бы окончательный вызов можно было сделать с любым количеством параметров. Именно здесь использование вариадных макросов решает проблему. Макросы BOOST_VMD_EMPTY и BOOST_VMD_IDENTITY имеют ту же функциональность, что и их аналоги Boost PP, но окончательный вызов может быть сделан с любым количеством параметров, и эти параметры просто игнорируются, когда выбор сделан BOOST_VMD_EMPTY или BOOST_VMD_IDENTITY.

Теперь о двух примерах, которые мы можем привести:

#include <boost/preprocessor/control/iif.hpp>
#include <boost/vmd/empty.hpp>
#define MACRO_CHOICE(parameter1,parameter2) \
    BOOST_PP_IIF(parameter1) \
        ( \
        MACRO_CALL_IF_PARAMETER_1, \
        SOME_FIXED_VALUE BOOST_VMD_EMPTY \
        ) \
    (parameter2)
#define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_parameters

или

#include <boost/preprocessor/control/iif.hpp>
#include <boost/vmd/identity.hpp>
#define MACRO_CHOICE(parameter1,parameter2) \
    BOOST_PP_IIF(parameter1) \
        ( \
        MACRO_CALL_IF_PARAMETER_1, \
        BOOST_VMD_IDENTITY(SOME_FIXED_VALUE) \
        ) \
    (parameter2)
#define MACRO_CALL_IF_PARAMETER_1(parameter2) some_processing_using_parameters

и наши макросы будут компилироваться без ошибок предварительной обработки и работать так, как ожидалось. Как BOOST_VMD_EMPTY, так и BOOST_VMD_IDENTITY принимают любое количество параметров в своем обращении, что делает их полезными для окончательного вызова независимо от того, что передается.

Usage for BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY

Для использования макроса BOOST_VMD_EMPTY включите общий заголовок:

#include <boost/vmd/vmd.hpp>

или включить конкретный заголовок:

#include <boost/vmd/empty.hpp>

Для использования макроса BOOST_VMD_IDENTITY используется общий заголовок:

#include <boost/vmd/vmd.hpp>

или включить конкретный заголовок:

#include <boost/vmd/identity.hpp>
Using BOOST_VMD_EMPTY and BOOST_VMD_IDENTITY with VC++

К сожалению, препроцессор Visual C++ имеет проблему, когда макрос расширяется до чего-то, за чем следует вариадный макрос. Это происходит при использовании BOOST_VMD_EMPTY после некоторого непустого расширения или эквивалентного использования BOOST_VMD_IDENTITY. Как бы странно это ни звучало, проблема препроцессора VC++ обычно решается путем объединения результата с помощью BOOST_PP_CAT с пустым значением. Но, опять же, многие нестандартные модели поведения VC++ трудно понять или даже отследить.

Чтобы сделать этот метод прозрачным при использовании со стандартом C++, соответствующим препроцессору или VC++. Нестандартный препроцессор BOOST_VMD_IDENTITY_RESULT макрос передает ему один параметр, который является результатом, возвращенным из макроса, который использует BOOST_VMD_IDENTITY (или его эквивалентное использование BOOST_VMD_EMPTY).

Приведем пример MACRO_CHOICE выше, если у вас есть другой макрос, вызывающий MACRO_CHOICE. Просто включите это обращение в BOOST_VMD_IDENTITY_RESULT. Как в самом простом:

#include <boost/vmd/identity.hpp>
#define CALLING_MACRO_CHOICE(parameter1,parameter2) \
    BOOST_VMD_IDENTITY_RESULT(MACRO_CHOICE(parameter1,parameter2))

В качестве альтернативы вы можете изменить MACRO_CHOICE, чтобы его реализация и использование были:

#include <boost/preprocessor/control/iif.hpp>
#include <boost/vmd/identity.hpp>
#define MACRO_CHOICE(parameter1,parameter2) \
    BOOST_VMD_IDENTITY_RESULT \
        ( \
        BOOST_PP_IIF(parameter1) \
            ( \
            MACRO_CALL_IF_PARAMETER_1, \
            BOOST_VMD_IDENTITY(SOME_FIXED_VALUE) \
            ) \
        (parameter2) \
        )
#define CALLING_MACRO_CHOICE(parameter1,parameter2) \
    MACRO_CHOICE(parameter1,parameter2)

Использование BOOST_VMD_EMPTY и BOOST_VMD_IDENTITY таким образом гарантирует, что они могут использоваться без проблем предварительной обработки с VC++ или любым стандартным препроцессором C++.

Usage for BOOST_VMD_IDENTITY_RESULT

BOOST_VMD_IDENTITY_RESULT находится в том же файле заголовка, что и BOOST_VMD_IDENTITY, поэтому используйте BOOST_VMD_IDENTITY_RESULT Макро либо включает общий заголовок:

#include <boost/vmd/vmd.hpp>

или включить конкретный заголовок:

#include <boost/vmd/identity.hpp>

PrevUpHomeNext

Статья Generating emptiness and identity раздела Chapter 1. The Variadic Macro Data Library 1.9 Useful variadic macros not in Boost PP может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Useful variadic macros not in Boost PP ::


реклама


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

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