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个)参数按如下顺序调用了宏:

std::map<int

char>

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.MPLBOOST_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)需要在指定类型上增加或移除引用。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刚买的小狗怕人怎么办 一年级孩子字写不好怎么办 小狗三天没吃了怎么办 捡到一只流浪猫怎么办 仓鼠四肢红肿圈状怎么办 泰迪的鼻子干燥怎么办 小狗眼睛有白色浓稠物怎么办 流浪狗生了小狗怎么办 学生字写得很差怎么办 猫身上粘老鼠胶怎么办 抄东西抄的手疼怎么办 皮质物品被油性笔划了怎么办 在小区猫丢了怎么办 母猫把小猫丢了怎么办 小狗不吃东西没精神怎么办 小狗的鼻子烂了怎么办 狗老是在家拉尿怎么办 狗狗鼻子有点干怎么办 狗的鼻头不黑了怎么办 金毛鼻头不黑怎么办 金毛毛掉了不长怎么办 狗狗鼻子烂了怎么办 小比熊鼻子不黑怎么办 狗狗鼻子起皮怎么办 金鱼身子弯了是怎么办 属狗的纹龙怎么办 卫生间的墙空的怎么办 花生苗长得好怎么办 菊花上面的白虫怎么办 小狗不吃东西还吐怎么办 小狗呕吐不吃东西没精神怎么办 小狗生病了不吃东西怎么办 小兔子腿摔了怎么办 刺猬葡萄我们骄傲我们该怎么办 小狗被邻居家大狗咬死了怎么办 狗狗死胎在腹中怎么办 小狗不吃饭没精神怎么办 虎皮鹦鹉生蛋了怎么办 钢笔替换芯干了怎么办 水芯钢笔不出水怎么办 被红斑蛇咬了怎么办