boost BOOST_IDENTITY_TYPE
来源:互联网 发布:交友网站软件下载 编辑:程序博客网 时间:2024/06/05 08:18
目录
动机
解决方案
模板
抽象类型
用法
实现
用户手册
此库允许用圆括号包装类型,使这些类型可以直接当作宏参数传递
动机
考虑实现用类型type定义一个变量varn 功能的宏:
#define VAR(type, n) type var ## nVAR(int, 1); // OK.VAR(std::map<int, char>, 2); // Error.
第一个宏调用可以正常的定义一个int类型的var1变量,但是第二个宏调用会产生一个类似如下信息的预编译错误:
error: macro "VAR" passed 3 arguments, but takes just 2
这是由于当作宏参数传递的std::map类型中有没有被圆括号()包装的逗号。预处理器认为没有被圆括号包装的逗号是宏参数的分隔符,所以它认为总共有3个(而不是2个)参数按如下顺序调用了宏:
1 std::map<int
2 char>
3 2
请注意,对于不同的编译器,预处理器只能识别圆括号()。尖括号<>和方括号[]在解析宏参数的时候都不能被预处理器识别。
解决方案
在某些情况下,可以通过避免直接用类型调用宏来解决这个问题。例如,可以用typedef重定义原来的类型表达式:
typedef std::map<int, char> map_type;VAR(map_type, 3); // OK.
当不希望或者不太可能这样的时候,头文件boost/utility/identity_type.hpp中定义了一个BOOST_IDENTITY_TYPE宏来解决这个问题,这个宏保证了类型表达式是宏的一个参数。
#include <boost/utility/identity_type.hpp>VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.
BOOST_IDENTITY_TYPE宏被扩展成了一个在编译时计算指定类型的表达式。指定类型没有被分割多个宏参数,因为它总是被一对额外的圆括号()包装起来。事实上,总共使用了2对圆括号:调用BOOST_IDENTITY_TYPE(...) 宏的圆括号,和包装传递进BOOST_IDENTITY_TYPE((...))宏的类型参数的内部圆括号。
此宏对任何支持的C++03 编译器都有效(它没有使用变长参数宏)。
模板
This macro must be prefixed by typename when used within templates. For example, let's program a macro that declares a function parameter named with the specified type (see also template.cpp):
当和模板一起使用的时候,必须在宏调用的前面加上typename。例如,实现一个定义一个类型为type的变量argn 功能的宏:
#define ARG(type, n) type arg ## ntemplate<typename T>void f( // Prefix macro with `typename` in templates. ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1)) { std::cout << arg1[0] << std::endl;}std::map<int, char> a;a[0] = 'a'; f<char>(a); // OK...// f(a); // ... but error.
值得注意的是,模板参数char必须在函数调用的时候显式指定,如f<char>(a)。事实上,当用BOOST_IDENTITY_TYPE宏包装函数模板参数的时候,模板参数在函数调用f(a)时不能被编译器自动推导出来(类模板没有这个限制,因为类模板参数总是必须被显式指定)。也就是说,如果不使用BOOST_IDENTITY_TYPE宏,C++编译器一般都能自动的推导出函数模板参数:
template<typename T>void g(std::map<int, T> arg1) { std::cout << arg1[0] << std::endl;}g<char>(a); // OK...g(a); // ... and also OK.
抽象类型
当用抽象类型(有一个以上纯虚函数的类)调用BOOST_IDENTITY_TYPE宏时,一些编译器(比如GCC)会报错。这个问题可以通过对类型增加和移除引用操作来解决。
比如实现一个Template Meta-Programming (TMP) 元函数静态断言的宏(和Boost.MPL中BOOST_MPL_ASSERT类似)。BOOST_IDENTITY_TYPE宏可以用来将多模板参数的元函数传进断言宏。在这种情况下,如果元函数是一个抽象类型,则它需要对类型进行增加或移除引用操作。
#define TMP_ASSERT(metafunction) \ BOOST_STATIC_ASSERT(metafunction::value)template<typename T, bool b>struct abstract { static const bool value = b; virtual void f(T const& x) = 0; // Pure virtual function.};TMP_ASSERT( boost::remove_reference< // Add and remove BOOST_IDENTITY_TYPE(( // reference for boost::add_reference< // abstract type. abstract<int, true> >::type )) >::type);
使用
BOOST_IDENTITY_TYPE宏既可以在调用用户自定义宏时使用,也可以在用户自定义宏实现里面调用(正如下面的例子)。当在用户自定义宏实现中使用BOOST_IDENTITY_TYPE宏时,用户自定义宏调用者必须指定额外的圆括号:
#define TMP_ASSERT_PAREN(parenthesized_metafunction) \ /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \ BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) #define TMP_ASSERT(metafunction) \ BOOST_STATIC_ASSERT(metafunction::value) // Specify only extra parenthesis `((...))`.TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>)); // Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
值得注意的是,即使这里宏参数中并没有包含逗号,调用者都必须指定额外的圆括号:
TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
实现
BOOST_IDENTITY_TYPE宏实现如下:
#include <boost/type_traits/function_traits.hpp> #define BOOST_IDENTITY_TYPE(parenthesized_type) \ boost::function_traits<void parenthesized_type>::arg1_type
类型必须被圆括号包装(std::map<int, char>),这样之后,即使类型中有逗号,它也会能被当作单个宏参数。之后,括起来的类型转换成一个返回void并且带有唯一指定参数的函数类型void (std::map<int, char>)。最终,第一参数arg1_type类型在编译时被function_traits元函数抽取出来。因此就获取到了原来被括号括起来的类型。
用户手册
头文件<boost/utility/identity_type.hpp>
用圆括号包装类型表达式,使得类型表达式中即使有逗号也能当作宏参数传递。
BOOST_IDENTITY_TYPE(parenthesized_type)
宏BOOST_IDENTITY_TYPE
BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).
摘要
// In header: <boost/utility/identity_type.hpp>
BOOST_IDENTITY_TYPE(parenthesized_type)
描述
参数:
parenthesized_type
可以作为宏参数传递并且被一对圆括号包装的类型表达式,它可以包含任意多个逗号。
此宏对任何支持的C++03 编译器都有效(它没有使用变长参数宏)。
此宏在和模板一起使用的时候必须在前面加上typename。值得注意的是,当用此宏包装模板参数时,编译器不能自动推导出函数模板参数(模板参数必须在调用函数模板时显式指定)。
当用抽象类型调用此宏时,一些编译器(比如GCC)需要在指定类型上增加或移除引用。
- boost BOOST_IDENTITY_TYPE
- Boost
- boost
- boost
- Boost
- boost
- boost
- Boost
- Boost
- Boost
- boost
- boost
- Boost
- boost
- boost
- boost
- boost
- boost
- Fragment与Viewpager及FragmentStatePagerAdapter
- leetcode集锦 ( 不定期更新)
- C++ primer 读书笔记(4)
- MFC中的多线程设计
- javascript函数
- boost BOOST_IDENTITY_TYPE
- 网站二级导航标题特效
- js中call与apply用法
- RHEL6:中文环境切换成英文环境
- SQLServer内置函数
- JavaScript系统内置函数大全
- servlet 过滤器和监听器总结
- [LeetCode]Roman to Integer
- JAVA正则表达式 Pattern和Matcher