utility
utility库不是一个有统一主题的Boost库,而是包含了若干个很小但有用的工具。
本章开头介绍的noncopyable.swap都曾经被归类在utility库里(现在则属于core库),此外utility还包括其他很多个实用类,如 base_from_member、compressed_pair、checked_delete等。
BOOST_BINARY
BOOST_BINARY提供一组宏,用于实现简单的二进制常量表示,它类似于C++14标准里的二进制字面量“0bxxx”的用法。
BOOST_BINARY的定义位于<boost/utility/binary.hpp>中,也可以通过<boost/utility.hpp>间接包含,即:
#include<boost/utility/binary.hpp> //或者
#include<boost/utility.hpp>
它使用boost.preprocessor预处理元编程工具将一组或多组01数字在编译期展开成为一个八进制数字。每个数字组之间需要用空格分隔,每组可以容纳1个到8个0/1数字。
这里特别要注意的是,数字组的长度一定不能超过8个,由于预处理器宏展开的限制,嵌套层次太深会导致无法通过编译,报出一大堆错误。
cout << hex << showbase;
cout << BOOST_BINARY(0110) << endl;
cout << BOOST_BINARY(0110 1101) << endl;
cout << BOOST_BINARY(10110110 01) << endl;
cout << bitset<5>(BOOST_BINARY(0110)) << endl;
除了最基本最通用的 BOOST_BINARY宏之外,本组件还包含形如 BOOST_BINARY_XX的宏,其中的xx是标准的整数扩展,如 u(unsigned int)、UL(unsigned long)等,用以支持需要特定整数类型的地方。例如,long long对应的宏是 BOOST_BINARY_LL。
cout << BOOST_BINARY_UL(101 1001) << endl;
long long x = BOOST_BINARY_LL(1101);
cout << x << endl;
BOOST_BINARY宏提供了很好的初始化操作方法,在某些需要按位操作的情况下特别有用,比如使用std::bitset。而且 BOOST_BINARY宏都是在编译期展开的,没有任何运行时开销。
BOOST_CURRENT_FUNCTION
GCC编译器在C89的__FILE__和__LINE__之外定义了一些扩展宏,其中的__PRETTY_FUNCTION__宏可以表示函数名称,VC、intel C等编译器也定义有类似的宏,而C99标准则定义了__func__宏以实现同样的功能。
BOOST_CURRENT_FUNCTION宏使用变通的方法为C++补充了这个功能,更具可移植性。
用法
为了使用 BOOST_CURRENT_FUNCTION宏,需要包含<boost/current_function.hpp>,即
#include<boost/current_fuction.hpp>
只需要在代码中使用BOOST_CURRENT_FUNCTION宏,就可获得包含该宏的外围函数名称,它表现为一个包含完整函数声明的编译期字符串。如果BOOST_CURRENT_FUNCTION宏不处于任何函数作用域之内,则行为依编译器而不同。
double func()
{cout << BOOST_CURRENT_FUNCTION << endl;return 0.0;
}string str = BOOST_CURRENT_FUNCTION; //错误用法,不能用在函数作用域外int main()
{cout << str << endl;cout << __FUNCTION__ << endl;cout << BOOST_CURRENT_FUNCTION << endl;func();
}
程序使用GCC编译后运行结果如下:
top level
main
int main()
double func()
实现原理
读者可能会惊讶于BOOST_CURRENT_FUNCTION宏的奇特魔力,其实 BOOST_CURRENT_FUNCTION宏并不神秘。它的实现代码实际上相当地简单,仅仅是针对各种编译器把编译器特定的宏定义为 BOOST_CURRENT_FUNCTION,因此它的能力完全依赖于编译器。
例如对于GCC,BOOST_CURRENT_FUNCTION是:
#define BOOST_CURRENT_FUCTION __PRETTY_FUNCTION__
虽然BOOST_CURRENT_FUNCTION的功能和实现都很简单,但它的确为函数名称的显示提供了一个通用的解决办法,在配合抛出异常或者输出诊断日志时非常有用。
代码示例
采用LLVM-clang-cl编译
#include <bitset>
#include <iostream>
using namespace std;#include <boost/utility.hpp>//
void case1()
{cout << hex << showbase;cout << BOOST_BINARY(0110) << endl;cout << BOOST_BINARY(0110 1101) << endl;cout << BOOST_BINARY(10110110 01) << endl;cout << bitset<5>(BOOST_BINARY(0110)) << endl;cout << BOOST_BINARY_UL(101 1001) << endl;long long x = BOOST_BINARY_LL(1101);cout << x << endl;}//
#include <boost/current_function.hpp>double func()
{cout << BOOST_CURRENT_FUNCTION << endl;return 0.0;
}string str = BOOST_CURRENT_FUNCTION; //错误用法,不能用在函数作用域外void case2()
{cout << str << endl;cout << __FUNCTION__ << endl;cout << BOOST_CURRENT_FUNCTION << endl;func();
}//int main()
{case1();case2();
}