上下文对象 (The Context Object)

介绍
头文件 'wave/context.hpp' 概要
公共类型定义
模板参数
成员函数

引言

boost::wave::context<>对象是该库中主要的、用户可见的对象。Wave它的存在是为了生成一对迭代器,在对这些迭代器进行解引用时,将返回预处理后的标记(tokens)。此外,它还用于控制预处理的其他方面,例如:

 包含文件搜索路径,定义了在使用#include <...>and#include "..."指令
 包含指令时搜索文件的位置;哪些宏需要预定义,以及哪些预定义宏需要取消定义;
 其他几个选项,例如控制是否启用 C++ 标准的若干扩展(例如变长参数和占位符)。

头文件 wave/cpp_context.hpp 概要

namespace boost {
namespace wave {

struct this_type {};

template <
typename Iterator, typename LexIterator,
typename InputPolicy, typename ContextPolicy,
typename Derived = this_type
>
class context : public InputPolicy
{
typedef <unspecified> token_sequence_type;

public:

typedef pp_iterator<context> iterator_type;
typedef Token token_type;
typedef typename token_type::position_type position_type;
typedef std::list<token_type> token_sequence_type;

// constructor
context(Iterator const &first_,
Iterator const &last_,
char const *fname = "<Unknown>",
ContextPolicy const& ctx_policy = ContextPolicy())

// iterator interface
iterator_type begin() const;
iterator_type begin(Iterator const &first,
Iterator const &last) const;
iterator_type end() const;

// maintain include paths
bool add_include_path(char const *path_);
bool add_sysinclude_path(char const *path_);
void set_sysinclude_delimiter();

size_t get_iteration_depth() const;

// maintain defined macros
template <typename String>
bool add_macro_definition(String macrostring,
bool is_predefined = false);
template <typename String>
bool add_macro_definition(StringT const &name,
position_type const& pos, bool has_params,
std::vector<token_type> &parameters,
token_sequence_type &definition,
bool is_predefined = false)

template <typename String>
bool is_defined_macro(String const &name) const;
template <typename String>
bool remove_macro_definition(String const &name,
bool even_predefined = false);
void reset_macro_definitions();
template <typename String>
bool get_macro_definition(
String const &name, bool &is_function_style,
bool
&is_predefined, position_type &pos,
std::vector<token_type> &parameters,
token_sequence_type &definition) const;

typedef <unspecified> macromap_type;
typedef typename macromap_type::name_iterator name_iterator;
typedef typename macromap_type::const_name_iterator const_name_iterator;

name_iterator macro_names_begin();
name_iterator macro_names_end();
const_name_iterator macro_names_begin() const;
const_name_iterator macro_names_end() const;

// other options
void set_language(language_support enable);
language_support get_language() const;

void set_max_include_nesting_depth(std::size_t new_depth);
size_t get_max_include_nesting_depth() const;

// get the Wave version information
static std::string get_version();
static std::string get_version_string();
};

} // namespace wave
} // namespace boost

模板参数

boost::wave::context对象具有三个模板参数,用于指定其操作的具体行为。下表详细描述了这些参数。

所需的模板参数boost::wave::context
Iterator

底层迭代器的类型,通过它访问输入流。
这至少应该是一个forward_iterator类型的迭代器。

LexIterator

由库使用的词法分析器类型,Wave用于识别输入流中的标记(tokens)。

InputPolicy

输入策略类的类型,允许自定义 Wave 库的行为以及在包含和打开被包含文件时要使用的迭代器类型。

ContextPolicy

上下文策略类的类型,允许自定义预处理行为的不同方面。此策略的要求及其实现的可选自定义点在此处描述。    

Derived

从上下文类型派生的类型(如果有)。此模板参数是可选的,默认为 'this_type',这意味着将假定不存在派生类型而直接使用上下文类型。

有关要使用的词法分析器类型的更多信息,请参阅词法分析器接口

如果省略模板参数InputPolicy,则使用模板boost::wave::iteration_context_policies::load_file_to_string。有关输入策略的更多信息,请参阅主题输入策略

如果省略模板参数 ContextPolicy,则使用boost::wave::context_policies::eat_whitespace策略类型,它实现了一些正常(默认)执行所需的某些基本预处理钩子。有关上下文策略的更多信息,请参阅主题上下文策略

公有类型定义 (Public Typedefs)

boost::wave::context模板定义了以下公有类型定义,这些定义在利用此类时可能会很有用:

由模板参数定义的公有类型定义,boost::wave::context
iterator_type

Iterator由提供的模板参数定义,context类被实例化。

lex_type

LexIterator由提供的模板参数定义,context类被实例化。

定义的公共类型定义

标记类型,由生成的context迭代器返回。此类型取自LexIterator提供的模板参数,context类被实例化。

input_policy_type

InputPolicy由提供的模板参数定义,context类被实例化。

context_policy_type

ContextPolicy由提供的模板参数定义,context类被实例化。

position_type

每个返回的标记中包含的位置信息的类型,它描述了识别给定标记的点。

成员函数

构造函数

    context(Iterator const &first, 
Iterator const &last, char const *filename,
ContextPolicy const& ctx_policy);

在由一对辅助迭代器给出的输入流之上构造一个上下文对象[first, last)。迭代器至少应该是forward_iterator类型的迭代器。filename 参数仅供参考。此字符串用于指示输入流中的标记位置,不会针对文件系统进行验证。如果未提供 filename 参数,则默认为 "<Unknown>"。如果未提供 ctx_policy 参数,则默认为默认构造的ContextPolicy对象中的边描述符。

此外,宏符号表将填充预定义宏,并且当前参考目录将设置为给定文件名的路径。如果此文件名未引用有效的文件系统项目,则当前参考目录将设置为当前系统目录。(当前参考目录是在处理#include "..."指令期间用作目标目录的文件系统路径)。

迭代器接口

context::beginandcontext::end函数返回的一对迭代器是访问预处理器引擎中预处理标记的主要接口。在给定的迭代器范围内进行迭代时[begin, end),将返回预处理后的 C++ 标记,这些标记是根据底层输入流即时生成的。返回的迭代器在概念上属于forward_iterator类型如何,此操作的时间复杂度均为 O(V + E)

begin

    iterator_type begin();
iterator_type begin(Iterator const &first,
Iterator const &last, );

初始化并返回预处理标记流的起始迭代器。由参数指定的迭代器对 [first, last)指定了要预处理的输入序列。此函数的第一个版本使用构造函数指定的输入流。 

end

    iterator_type end() const;

初始化并返回流结束迭代器,用于进行比较以检测预处理标记流的结束。

维护包含路径

Wave库为包含文件维护两个独立的搜索路径。一个是用户包含文件搜索路径,一个是系统包含文件搜索路径。在调用 set_sysinclude_delimiter() 函数之前,使用 add_include_path() 函数指定的任何目录仅在#include "..."指令的情况下被搜索,它们不会被#include <file>指令搜索。即这些目录被添加到用户包含搜索路径中。

如果在调用函数 set_sysinclude_delimiter() 之后,使用 add_include_path() 函数指定了其他目录,则这些目录将针对所有#include指令进行搜索。即这些目录被添加到系统包含搜索路径中。

此外,调用函数 set_sysinclude_delimiter() 会禁止将当前参考目录作为#include "..."指令的第一个搜索目录。因此,仅当通过调用函数 add_include_path(".") 明确请求时,才会搜索当前参考目录。

同时调用 set_sysinclude_delimiter()add_include_path(".") 这两个函数,可以让您精确控制哪些目录在当前目录之前搜索,哪些在当前目录之后搜索。

这些函数是仿照流行的 gcc 编译器所实现的命令行行为而设计的。

add_include_path

    bool add_include_path(char const *path);

将给定的文件系统路径添加到用户包含搜索路径中。在调用 set_sysinclude_delimiter() 之后,此函数将给定的文件系统路径添加到系统包含搜索路径中。请注意,给定的路径会根据文件系统进行验证。

如果给定的路径字符串不构成有效的文件系统目录项的名称,则函数返回false。如果给定的路径已成功添加到相关的包含搜索路径中,则函数返回true.

add_sysinclude_path

    bool add_sysinclude_path(char const *path);

将给定的文件系统路径添加到系统包含搜索路径中。无论 add_include_path() 的运行模式如何,此函数都在系统包含搜索路径上运行。请注意,给定的路径会根据文件系统进行验证。

如果给定的路径字符串不构成有效的文件系统目录项的名称,则函数返回false。如果给定的路径已成功添加到系统包含搜索路径中,则函数返回true.

set_sysinclude_delimiter

    void set_sysinclude_delimiter();

切换 add_include_path() 函数的运行模式。默认情况下,给定的文件系统路径被添加到用户包含搜索路径中。在调用此函数之后,随后调用的 add_include_path() 将给定的文件系统路径添加到系统包含搜索路径中。此外,它还禁止将当前参考目录用作#include "..."指令的第一个搜索目录。

get_iteration_depth

    size_t get_iteration_depth() const;

返回实际的包含迭代深度,即在到达主(最顶层)迭代上下文之前,当前要从包含迭代上下文中退出的包含层级数。

维护已定义的宏

add_macro_definition

    bool add_macro_definition(
std::string macrostring, bool is_predefined);

将新的宏定义添加到宏符号表中。参数macrostring应包含以命令行格式定义的宏,即类似于MACRO(x)=definition的内容。下表更详细地描述了这种格式。参数is_predefined在定义预定义宏时应为 true,即在预处理输入流内部无法通过#undef指令取消定义的宏。如果未提供此参数,则默认为false.

定义宏的可能格式摘要
MACRO 定义MACRO为 1
MACRO= 定义MACRO定义为空
MACRO=definition 定义MACRO定义
MACRO(x) 定义MACRO(x)为 1
MACRO(x)= 定义MACRO(x)定义为空
MACRO(x)=definition 定义MACRO(x)定义

如果宏已定义且新定义与现有定义等效,则函数返回false;如果新宏已成功添加到宏符号表中,则返回 true。

如果给定的宏定义构成了重新定义,且新宏与已定义的宏不完全相同(在 C++ 标准定义的意义上),则函数会抛出相应的preprocess_exception.

is_defined_macro

    template <typename String>
bool is_defined_macro(String const &name) const;

返回具有给定名称的宏是否已定义,即是否包含在宏符号表中。

get_macro_definition

    template <typename String>
bool get_macro_definition(
String const &name, bool &is_function_style,
bool
&is_predefined, position_type &pos,
std::vector<token_type> &parameters,
token_sequence_type &definition) const;

允许检索有关宏定义的所有已知信息。参数名称指定了应返回其信息的宏名称。参数is_function_styleandis_predefined分别返回宏是被定义为函数式宏还是预定义宏。参数pos将包含宏定义时的位置。参数parameters将包含宏定义时的参数名称,参数定义将包含定义的标记序列(宏体)。

如果宏已定义且新定义与现有定义等效,则函数返回true如果宏已定义且请求的信息已成功检索,false否则。

remove_macro_definition

    template <typename String>
bool remove_macro_definition(
String const &name, bool even_predefined);

从宏符号表中移除具有给定名称的宏定义。此操作等同于在输入流中执行带有此#undef名称指令。如果参数even_predefinedtrue,则即使宏被定义为预定义宏,也会从宏符号表中移除。

但请注意,在任何情况下,以下宏都是不可取消定义的:__FILE__, __LINE__, __DATE__, __TIME__, __cplusplus, __STDC__。如果参数even_predefined未提供,则默认为false.

如果宏已定义且新定义与现有定义等效,则函数返回false,如果取消定义的宏未定义,则返回true否则。

如果不能移除要取消定义的宏(它是一个预定义宏且参数为even_predefined被设置为false或者是上述提到的不可取消定义的宏之一),函数将抛出一个preprocess_exception.

reset_macro_definitions

    void reset_macro_definitions(); 

将宏符号表重置为其初始状态,即取消定义所有用户定义的宏,并插入如此处所述的内部预定义宏。

macro_names_begin, macro_names_end

    name_iterator macro_names_begin();
name_iterator macro_names_end();
const_name_iterator macro_names_begin() const;
const_name_iterator macro_names_end() const;

macro_names_beginandmacro_names_end函数返回允许对所有已定义宏的名称进行迭代的迭代器。

获取版本信息

get_version

    static std::string get_version(); 

返回一个包含当前 Wave 版本的字符串,格式为 0xvvrsbbbb(这是等效十六进制数的字符串表示),其中 'vv' 是版本号,'r' 是发布号,'s' 是子版本号,'bbbb' 是构建号。可能的返回值类似于 0x00910454。返回的值与展开预定义宏__WAVE_VERSION__时插入到预处理标记流中的值相同。

get_version_str

    static std::string get_version_str(); 

返回一个包含当前 Wave 版本的字符串,格式为 "v.rr.ss.bbbb",其中 'v' 是版本号,'rr' 是发布号,'ss' 是子版本号,'bbbb' 是构建号。可能的返回值类似于 "0.9.1.454"。返回的值与展开预定义宏__WAVE_VERSION_STR__时插入到预处理标记流中的值相同。

控制扩展选项

set_language
get_language

    void set_language(language_support language, 
bool reset_macros = true);
language_support get_language() const;

此函数允许指定库工作的语言模式。Wave可能的语言模式由枚举类型定义language_support:

    enum language_support {
// support flags for C++98
support_normal = 0x01,
support_cpp = support_normal,

// support flags for C99

support_option_long_long = 0x02,
support_option_variadics = 0x04,
support_c99 = support_option_variadics | support_option_long_long | 0x08,

// support flags for C++11

support_option_no_newline_at_end_of_file = 0x20,
support_cpp0x = support_option_variadics | support_option_long_long |
support_option_no_newline_at_end_of_file | 0x10,
support_cpp11 = support_cpp0x,

// support flags for C++17
support_option_has_include = 0x10000,
support_cpp1z = support_option_variadics | support_option_long_long |
support_option_no_newline_at_end_of_file | support_option_has_include | 0x20000,
support_cpp17 = support_cpp1z

// support flags for C++20
support_option_va_opt = 0x40000,
support_cpp2a = support_option_variadics | support_option_long_long |
support_option_no_newline_at_end_of_file | support_option_has_include |
support_option_va_opt | 0x80000,
support_cpp20 = support_cpp2a,

// the mask for the main language settings

support_option_mask = 0xFFC0,

// additional fine tuning of the general behavior
support_option_emit_contline = 0x0040,
support_option_insert_whitespace = 0x0080,
support_option_preserve_comments = 0x0100,
support_option_no_character_validation = 0x0200,
support_option_convert_trigraphs = 0x0400,
support_option_single_line = 0x0800,
support_option_prefer_pp_numbers = 0x1000,
support_option_emit_line_directives = 0x2000,
support_option_include_guard_detection = 0x4000,
support_option_emit_pragma_directives = 0x8000
};

当与support_option_variadics一起使用时,将在普通 C++ 模式下启用对变长参数、占位符和operator _Pragma()的支持。当与support_option_long_long一起使用时,将在 C++ 模式下启用对 long long 后缀的支持。

support_c99切换到 C99 语言支持,默认启用变长参数、占位符、运算符 _Pragma和 long long 后缀。此外,它还禁用 C++ 特有的标记,例如'->*', '.*', '::'等等。

support_option_...值应与主语言设置(support_normalandsupport_c99) .

在此过程中,库将识别两种形式的包含卫护:

 #ifndef INCLUDE_GUARD_MACRO
#define INCLUDE_GUARD_MACRO
...
#endif
or
#if !defined(INCLUDE_GUARD_MACRO)
#define INCLUDE_GUARD_MACRO
...
#endif

请注意,第二种形式中的括号是可选的(即!defined INCLUDE_GUARD_MACRO也将起作用)。代码允许在 #if/#ifndef 之前以及在包含卫护的最终 #endif 之后出现任何空格、换行符和单个 '#' 标记,以便被识别为包含卫护。

此标志默认开启,因此如果您不希望库自动识别包含卫护,则需要显式重置它。

如果参数reset_macros为 true,则set_language函数会在内部重置已定义的宏列表,因此请注意不要在已经定义了自己的宏之后调用它。

set_max_include_nesting_depth
get_max_include_nesting_depth

    void set_max_include_nesting_depth(size_t new_depth); 
size_t get_max_include_nesting_depth() const;

这些函数允许设置或获取Wave库支持的最大可能包含文件嵌套深度。此深度的初始值由预处理常量确定WAVE_MAX_INCLUDE_LEVEL_DEPTH(参见此处)。