config
config库主要是提供给Boost库开发者(而不是库用户)使用,它将程序的编译配置分解为三个正交的部分:平台、编译器和标准库,帮助他们解决特定平台特定编译器的兼容问题。
一般来说,config库不应该被库用户使用,不过在这个库里,我们也可以找到几个有用的小工具(其实在第1章我们就已经用到了config库里的BOOST_PLATFORM等宏)。
BOOST_STRINGIZE
宏BOOST_STRINGIZE可以将任意字面量转换为字符串。为了使用BOOST_STRINGIZE宏,需要包含头文件<boost/config/suffix.hpp>,即:
#include<boost/config/suffix.hpp>
BOOST_STRINGIZE是一个宏,这一点很重要,意味着它仅能用于编译期(准确地说是编译前预处理时),不支持运行时转换。如果要在运行时转换数字或者其他变量到字符串,则使用lexical_cast。
示范 BOOST_STRINGIZE用法的代码如下,其中的__LINE__是C标准中定义的内置宏,表示程序的行号,是一个long型整数:
cout << BOOST_STRINGIZE(__LINE__) << endl;
cout << std::boolalpha << (string("22") == BOOST_STRINGIZE(__LINE__)) << endl;
int x = 255;
cout << BOOST_STRINGIZE(x) << endl;
代码的前两条语句运用了BOOST_STRINGIZE,把编译期的整数转换成了字符串,而第三个 BOOST_STRINGIZE因无法处理运行时的整数变量,只能把它转换成字面意义的字符串。
BOOST_STRINGIZE最常见的用途是在泛型编程中将编译期常数转换成字符串,在调试或者输出日志时相当方便,如boost.exception中就用到了BOOST_STRINGIZE。
BOOST_STATIC_CONSTANT
C++标准允许直接在类声明中为静态整型成员变量赋初始值,但并不是所有编译器都实现了这个特性。如果使用的编译器缺乏这个能力,那么只能使用enum来变通实现。
下面的代码定义了一个类static_int,它同时使用了这两种方法:
struct static_int
{
static const int v1 = 10; //静态整型变量赋初值
enum { v2 = 20 }; //枚举得到编译期整数值
int a[v2];
};
BOOST_STATIC_CONSTANT宏为这个解决问题提供了一个可移植的简便语法:
BOOST_STATIC_CONSTANT(type, assignment)
使用BOOST_STATIC_CONSTANT宏,我们无须担心编译器的能力限制,代码会更具可移植性。它的用法就像是一个普通的变量赋值语句,只是使用了略微有些变形的宏形式。
之前的例子可以用BOOST_STATIC_CONSTANT宏改写如下:
struct static_int
{
BOOST_STATIC_CONSTANT(int, v1 = 10);
BOOST_STATIC_CONSTANT(int, v2 = 20);
};
这样的代码比单纯的静态成员变量声明或者enum更清晰,具可读性。
代码示例
#include <iostream>
using namespace std;
#include <boost/core/ignore_unused.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION <= 106400
#include <boost/config/suffix.hpp>
#else
#include <boost/config/detail/suffix.hpp>
#endif
using namespace boost;
//
void case1()
{
cout << BOOST_STRINGIZE(__LINE__) << endl;
cout << std::boolalpha << (string("22") == BOOST_STRINGIZE(__LINE__)) << endl;
int x = 255;
cout << BOOST_STRINGIZE(x) << endl;
ignore_unused(x);
}
//
struct static_int
{
BOOST_STATIC_CONSTANT(int, v1 = 10);
BOOST_STATIC_CONSTANT(int, v2 = 20);
};
//
int main()
{
case1();
}