| 上下文对象 (The Context Object) | ![]() |
![]() |
![]() |
该boost::wave::context<>对象是该库中主要的、用户可见的对象。Wave它的存在是为了生成一对迭代器,在对这些迭代器进行解引用时,将返回预处理后的标记(tokens)。此外,它还用于控制预处理的其他方面,例如:
包含文件搜索路径,定义了在使用#include <...>and#include "..."指令
包含指令时搜索文件的位置;哪些宏需要预定义,以及哪些预定义宏需要取消定义;
其他几个选项,例如控制是否启用 C++ 标准的若干扩展(例如变长参数和占位符)。
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> ¶meters,
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> ¶meters,
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 |
底层迭代器的类型,通过它访问输入流。 |
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策略类型,它实现了一些正常(默认)执行所需的某些基本预处理钩子。有关上下文策略的更多信息,请参阅主题上下文策略。
该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)。
iterator_type begin();
iterator_type begin(Iterator const &first,
Iterator const &last, );
初始化并返回预处理标记流的起始迭代器。由参数指定的迭代器对 [first, last)指定了要预处理的输入序列。此函数的第一个版本使用构造函数指定的输入流。
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 编译器所实现的命令行行为而设计的。
bool add_include_path(char const *path);
将给定的文件系统路径添加到用户包含搜索路径中。在调用 set_sysinclude_delimiter() 之后,此函数将给定的文件系统路径添加到系统包含搜索路径中。请注意,给定的路径会根据文件系统进行验证。
如果给定的路径字符串不构成有效的文件系统目录项的名称,则函数返回false。如果给定的路径已成功添加到相关的包含搜索路径中,则函数返回true.
bool add_sysinclude_path(char const *path);
将给定的文件系统路径添加到系统包含搜索路径中。无论 add_include_path() 的运行模式如何,此函数都在系统包含搜索路径上运行。请注意,给定的路径会根据文件系统进行验证。
如果给定的路径字符串不构成有效的文件系统目录项的名称,则函数返回false。如果给定的路径已成功添加到系统包含搜索路径中,则函数返回true.
void set_sysinclude_delimiter();
切换 add_include_path() 函数的运行模式。默认情况下,给定的文件系统路径被添加到用户包含搜索路径中。在调用此函数之后,随后调用的 add_include_path() 将给定的文件系统路径添加到系统包含搜索路径中。此外,它还禁止将当前参考目录用作#include "..."指令的第一个搜索目录。
size_t get_iteration_depth() const;
返回实际的包含迭代深度,即在到达主(最顶层)迭代上下文之前,当前要从包含迭代上下文中退出的包含层级数。
bool add_macro_definition(
std::string macrostring, bool is_predefined);
将新的宏定义添加到宏符号表中。参数macrostring应包含以命令行格式定义的宏,即类似于MACRO(x)=definition的内容。下表更详细地描述了这种格式。参数is_predefined在定义预定义宏时应为 true,即在预处理输入流内部无法通过#undef指令取消定义的宏。如果未提供此参数,则默认为false.
定义宏的可能格式摘要 MACRO定义MACRO为 1MACRO=定义MACRO定义为空MACRO=definition定义MACRO和定义MACRO(x)定义MACRO(x)为 1MACRO(x)=定义MACRO(x)定义为空MACRO(x)=definition定义MACRO(x)和定义如果宏已定义且新定义与现有定义等效,则函数返回false;如果新宏已成功添加到宏符号表中,则返回 true。
如果给定的宏定义构成了重新定义,且新宏与已定义的宏不完全相同(在 C++ 标准定义的意义上),则函数会抛出相应的preprocess_exception.
template <typename String>
bool is_defined_macro(String const &name) const;
返回具有给定名称的宏是否已定义,即是否包含在宏符号表中。
template <typename String>
bool get_macro_definition(
String const &name, bool &is_function_style,
bool &is_predefined, position_type &pos,
std::vector<token_type> ¶meters,
token_sequence_type &definition) const;
允许检索有关宏定义的所有已知信息。参数名称指定了应返回其信息的宏名称。参数is_function_styleandis_predefined分别返回宏是被定义为函数式宏还是预定义宏。参数pos将包含宏定义时的位置。参数parameters将包含宏定义时的参数名称,参数定义将包含定义的标记序列(宏体)。
如果宏已定义且新定义与现有定义等效,则函数返回true如果宏已定义且请求的信息已成功检索,false否则。
template <typename String>
bool remove_macro_definition(
String const &name, bool even_predefined);
从宏符号表中移除具有给定名称的宏定义。此操作等同于在输入流中执行带有此#undef的名称指令。如果参数even_predefined是true,则即使宏被定义为预定义宏,也会从宏符号表中移除。
但请注意,在任何情况下,以下宏都是不可取消定义的:__FILE__, __LINE__, __DATE__, __TIME__, __cplusplus, __STDC__。如果参数even_predefined未提供,则默认为false.
如果宏已定义且新定义与现有定义等效,则函数返回false,如果取消定义的宏未定义,则返回true否则。
如果不能移除要取消定义的宏(它是一个预定义宏且参数为even_predefined被设置为false或者是上述提到的不可取消定义的宏之一),函数将抛出一个preprocess_exception.
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__时插入到预处理标记流中的值相同。
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) .
- 如果support_option_insert_whitespace标志被设置时,Wave库会在标记之间插入额外的空格,前提是两个标记的连接字符串表示会形成另一个有效的 C++ 标记。这对于避免误读生成的输出非常重要,尤其是如果该输出随后要由 C++ 编译器处理。
- 如果support_option_preserve_comments标志被设置时,Wave库会保留源代码中几乎所有的注释。唯一不保留的注释是宏定义中包含的注释。如果未设置此标志,所有注释都将被单个空格替换。
- 如果support_option_no_character_validation标志被设置时,Wave库不会验证通用字符字面量(以'u1234'或'U12345678'的形式给出)是否在允许的值范围内。此标志仅供测试框架内部使用,库的用户很少会用到。
- 如果support_option_convert_trigraphs标志被设置时,Wave库会将所有出现的三字符组替换为其对应的非三字符组序列(即'??='被替换为'#'等)。默认情况下不执行替换。
- 如果support_option_single_line标志被设置时,Wave库运行在单行模式下,除其他外,如果处理输入的最后一行没有以换行符结尾,它将不会报告错误。此标志主要由测试框架在内部使用,库的用户很少会使用。要禁用文件末尾的换行符检查,请使用support_option_no_newline_at_end_of_file(C++11 及更高版本的默认设置)。
- 如果support_option_prefer_pp_numbers标志被设置时,Wave库被指示正确识别输入流中的预处理数字(pp-number)。这些在返回给调用应用程序之前会被识别为“正常”数字标记。默认设置该标志,仅用于内部目的,库的用户很少会重置它。
- 如果设置了 support_option_emit_line_directives 标志,Wave库将在生成的标记流中适当地发出 #line 指令。此标志默认设置,要防止库生成 #line 指令,必须显式重置它。
- 如果设置了 support_option_include_guard_detection 标志,Wave库将在处理包含文件期间尝试自动识别包含卫护(include guards)。包含包含卫护的文件将像包含 #pragma once 一样处理,即这些文件不会被打开两次,即使在第二个 #include 语句中指定也是如此。
在此过程中,库将识别两种形式的包含卫护:
#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 之后出现任何空格、换行符和单个 '#' 标记,以便被识别为包含卫护。
此标志默认开启,因此如果您不希望库自动识别包含卫护,则需要显式重置它。
- 如果support_option_emit_pragma_directives标志被设置时,Wave库将向输出发出所有未知的 #pragma 指令。仅当在编译期间将BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES定义为不等于零的值时,此支持选项才会被识别(更多信息请参见此处)。
- 如果support_option_emit_contlines标志被设置时,Wave库将发出在输入中遇到的所有反斜杠换行符序列。它将为每个此类字符序列生成一个T_CONTLINE标记。请注意,仅自定义 SLex 词法分析器模块支持此选项。有关工作示例,请参见 cpp_tokens 示例。
如果参数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(参见此处)。
![]() |
![]() |
版权所有 © 2003-2011 Hartmut Kaiser
根据 Boost Software License, Version 1.0 分发。(参见附带的 LICENSE_1_0.txt 文件或访问 https://boost.ac.cn/LICENSE_1_0.txt 副本)
最后更新日期2011年8月6日,星期六 20:22