ValueIncapsulator

Path: docs/ValueIncapsulator
Last Update: Mon Jun 04 14:34:35 +0400 2007

Шаблон ValueIncapsulator [C++]

Назначение

Шаблон ValueIncapsulator предназначен для генерации C++ классов, которые только инкапсулируют в себе несколько значений и предоставляют публичные методы для получения/изменения этих значений. Примерами таких классов могут быть классы, содержащие конфигурацию приложения. Например, пусть нужен класс, который содержит имя хоста и номер порта для подключения к этому хосту через TCP/IP. Без использования кодогенерации пришлось бы написать следующий C++ код:

        class host_config_t
                {
                private :
                        std::string  m_host;
                        short        m_port;
                public :
                        host_config_t()
                                :   m_port( 0 )
                                {}

                        const std::string & host() const { return m_host; }
                        void set_host( const std::string & v ) { m_host = v; }

                        short port() const { return m_port; }
                        void set_port( short v ) { m_port = v; }
                };

Но такого же результата можно достичь с использованием шаблона ValueIncapsulator:

        cpp_value_incapsulator :host_config_t do |c|
                c.decl_file :script_relative => "host_config.impl.hpp"
                c.impl_file :script_relative => "host_config.impl.cpp"

                c.attr_prefix "m_"
                c.attr :host, "std::string"
                c.attr :port, "short", default => 0
        end

Принцип работы

Шаблон ValueIncapsulator используется посредством метода cpp_value_incapsulator, который получает в качестве аргумента имя генерируемого C++ класса и требует наличие блока кода, в котором будут задаваться параметры кодогенерации. Этот блок кода вызывается внутри cpp_value_incapsulator с одним параметром: экземпляром класса RuCodeGen::ValueIncapsulator. С помощью именно этого экземпляра и задаются параметры кодогенерации.

После того, как блок кода внутри cpp_value_incapsulator отработает, шаблон создаст два генератора кода — один для генерации описания класса, второй для генерации реализации класса. В текущей версии ValueIncapsulator, описания и реализация класса должны размещаться в отдельных файлах, расположение и имена которых задаются посредством методов RuCodeGen::ValueIncapsulator#decl_file и RuCodeGen::ValueIncapsulator#impl_file. Созданные cpp_value_incapsulator генераторы запускаются на исполнение штатным образом при завершении работы скрипта.

Параметры шаблона ValueIncapsulator

Файлы описания/реализации генерируемого класса.

Имена и расположение файлов задается посредством методов decl_file и impl_file:

        c.decl_file <relative> => <name>

где <relative> это:

:absolute
задается абсолютное имя файла;
:script_relative
имя файла задается относительно расположения скрипта с описанием кодогенерации;
:cwd_relative
имя файла задается относительно текущего каталога.

Например:

        c.decl_file :script_relative => "h/decl.hpp"
        c.impl_file :script_relative => "decl.cpp"

Подробнее см. RuCodeGen::FilenameProducer#produce.

Префиксы/суффиксы для имен атрибутов

По умолчанию, ValueIncapsulator создает атрибуты сгенерированного класса с теми именами, которые были переданы в метод c.attr. Например, для описания:

        c.attr :host, "std::string"

будет сгенерирован атрибут host типа std::string. Если требуется, чтобы у атрибутов класса были специфические префиксы или/и суффиксы, то следует задать их с помощью методов attr_prefix, attr_suffix. Например:

        c.attr_prefix "m_"
        c.attr :host, "std::string"

приводит к генерации:

        std::string    m_host;

а описание:

        c.attr_suffix "_"
        c.attr :host, "std::string"

приводит к генерации:

        std::string    host_;

Можно задать одновременно и префикс, и суффикс.

Префиксы для методов getter-/setter-ов

По умолчанию, ValueIncapsulator создает методы getter-/setter-ы с теми именами, которые были переданы в метод c.attr. Например:

        c.attr :port, "short"

преобразуется в:

        short port() const;
        void port( short v__ );

С помощью методов getter_prefix и setter_prefix можно указать префикс для соответствующего типа методов. Например:

        c.getter_prefix "query_"
        c.attr :port, "short"

преобразуется в:

        short query_port() const;
        void port( short v__ );

Или:

        c.setter_prefix "set_"
        c.attr :port, "short"

приводит к:

        short port() const;
        void set_port( short v__ );

Можно задать одновременно префиксы для getter-ов и setter-ов.

Значения по умолчанию для атрибутов

По умолчанию, для всех атрибутов примитивных типов (см. RuCodeGen::ClassAttribute::PRIMITIVE_TYPES) в конструкторе задается значение 0. Для атрибутов, тип которого не относится к примитивным типам начальное значение вообще не задается. Если это не желательно и нужно назначить атрибуту специфическое значение, то его следует указать в методе attr:

        c.attr :host, "std::string", :default => "localhost"
        c.attr :port, "short", :default => 8080

Использование идентификаторов в качестве начальных значений атрибутов

Если начальное значение атрибута задается какой-либо C++ константой, элементом enum-а или даже вызовом C++ функции, то соответствующий C++ идентификатор нужно записывать в Ruby-коде в виде Symbol-а (идентификатора с предшествующим двоеточием):

        c.attr :host, "std::string", :default => :"get_default_host()"
        c.attr :port, "short", :default => :default_port

тогда в конструкторе инициализация атрибутов будет иметь вид:

        host( get_default_host() ),
        port( default_port )

Работа со значениями не примитивных типов

Если тип атрибута не является примитивным (см. RuCodeGen::ClassAttribute::PRIMITIVE_TYPES), то метод getter возвращает константную ссылку на атрибут, а метод setter получает константную ссылку в качестве аргумента. Например:

        c.attr :host, "std::string"

приводит к генерации:

        const std::string & host() const;
        void host( const std::string & v__ );

Если по каким-то причинам использовать ссылки не желательно, то это можно указать при описании атрибута:

        c.attr :host, "std::string", getter_returns_value => true

что приведет к генерации:

        std::string host() const;
        void host( std::string v__ );

Примеры использования кодогенератора cpp_value_incapsulator

Пример host_config

Пример cfg

[Validate]

Hosted by uCoz