促进 C++库

……其中一个世界。 赫伯·萨特安德烈亚历山德雷斯库,C类++编码标准

这是旧版本Boost的文档。单击此处查看此页面的最新版本。

第1章助力。功能/转发1.0

托比亚斯 施温格

根据Boost软件许可证1.0版进行分发。(见随附文件文件LICENSE_1_0.txt或复制到http://www.boost.org/LICENSE_1_0.txt)

目录

简要说明
背景
参考
致谢
工具书类

促进::转发适配器提供可重复使用的适配器函数对象的模板。它将RValues作为const的引用转发,同时将L值保留为-is。

结构  //只接受LValue的函数对象
{
    模板< 类别名 T0类, 类别名 T1类, 类别名 T2段 >
    空隙 操作人员()(T0类 & t0(吨), T1类 & t1时间, T2段 & t2时间) 常数;

    类型定义 空隙 结果类型;
};

//适配版本也接受RValues和forwards
//它们作为常量的参考,L值as-is
类型定义 促进::转发适配器<> (f);

另一个适配器,促进::轻量向前适配器允许转发在用户的一些帮助下,接受并打开引用包装(请参见促进。裁判)的引用参数,const限定所有其他参数。

目标函数必须与兼容促进。结果属于,适配器也是如此。

假设我们有一些函数(f)我们可以这样称呼:

(f)(123,变量(_variable));

现在我们要编写另一个泛型函数它可以以相同的方式调用,并返回一些调用(f)具有相同的参数。

(f)(123,变量(_variable)) == ((f),123,变量(_variable)).调用(_f)()

为什么?不管怎样,我们想这么做吗?

也许我们想跑步(f)几个次。或者我们可能想在另一个线程中运行它。也许我们只是想现在封装调用表达式,然后与其他代码一起使用它允许组合更复杂的表达式,以便使用C++模板并让编译器生成一些最终电话(f)在运行时(在其他话;应用通常称为表达式模板的技术)。

现在,如何我们做了吗?

坏消息是:这是不可能的。

之所以如此,是因为变量和表达式之间有细微的区别其计算值为:给定

整数 ;
整数 常数 z(z) = 0;

模板< 类别名 T型 > 空隙 功能1(T型 & x个);

我们可以打电话

功能1(); //x是指非接触物体
功能1(z(z)); //x是对常量对象的引用

哪里

功能1(1); //无法编译。

这样我们可以安全地功能1存储其引用参数,编译器将阻止我们存储引用具有临时生存期的对象。

重要的是要认识到非接触性以及对象是否绑定到非接触参考参数是两种不同的属性。后者是左值和右值之间的区别。名字来源于左手赋值表达式的右侧和右侧,因此L值通常是您可以分配给的值,R从右侧值临时结果手势。

 = 1+2;        //a是L值,1+2是产生R值的表达式,
//1+2=a;//通常没有意义。

函数1();       //有效,因为y是L值
//函数1(1+2);//无法编译,因为我们只得到了一个RValue。

如果我们在参数上添加常量限定,我们的函数也接受RValues:

模板< 类别名 T型 > 空隙 函数2(T型 常数 & x个);

//[…]功能范围:
函数2(1); //x是对常量临时对象的引用,
函数2(); //x是对常量对象的引用,而y不是常量,并且
函数2(z(z)); //x是对常量对象的引用,就像z一样。

在所有情况下,论点x个在里面函数2是符合条件的常量L值。我们可以使用函数重载来识别非静态LV值:

模板< 类别名 T型 > 空隙 功能3(T型 常数 & x个); // #1
模板< 类别名 T型 > 空隙 功能3(T型 & x个);       // #2

//[…]功能范围:
功能3(1); //x是对#1中常量临时对象的引用,
功能3(); //x是对#2中非接触对象的引用,并且
功能3(z(z)); //x是对1中常量对象的引用。

请注意,所有参数x个在里面重载函数功能3是L值。事实上,无法将RValue传输到函数中as-is在C++98中。还要注意,我们无法区分过去是什么常量限定L值和R值。

这是我们能得到的通用转发函数如上所述,通过C++98.参见这个转发问题进行非常详细的讨论,包括解决方案需要改变语言。

现在,为了实际实现它,我们需要为N个参数(每个参数)重载2^N个对于每个数量的参数(即2^(Nmax+1))-2^N分钟)。没错,这意味着编译时间的复杂性是O(2^N),然而这个系数很低,所以对于一个合理的数字(<10)来说效果很好参数的。

描述

其实例可使用LValue调用的函数对象适配器模板和RValue参数。R值参数作为对常量的引用转发类型LValues。

arity可以作为第二个数字非类型模板参数来限制转发到特定arity。如果是第三个数字非类型模板参数则第二个和第三个模板参数被视为最小值和最大arity。指定arity有助于改进诊断消息的可读性和编译时性能。

促进。结果属于可用于确定特定调用表达式的结果类型。

标题
#包括 <促进/功能性的/转发适配器.马力>
简介
命名空间 促进
{
    模板<  功能,
        整数 数量_或最小数量 = 未指明的, 整数 最大Arity = 未指明的 >
     转发适配器;
}

符号

F类

可能是常量限定的函数对象类型或其引用类型

(f)

可转换为的对象F类

传真

类型转发适配器<F类>

的实例对象传真,用初始化(f)

a0级...澳大利亚

参数到

目标函数调用的结果类型必须为

促进::结果<F类*(技术顾问0 [常数]&...坦桑尼亚 [常数]&])>::类型

哪里技术顾问0...坦桑尼亚表示的参数类型a0...澳大利亚.

表达式语义学

表达式

语义学

传真((f))

创建适配器,用初始化目标函数(f).

传真()

创建适配器,尝试使用F类默认构造函数。

(a0...澳大利亚)

电话(f)带有自变量a0...澳大利亚.

限制

可以定义宏BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY来设置最大调用arity。默认为6。

复杂性

预处理时间:O(2^N),其中N是arity极限。编译时间:O(2^N),其中N取决于arity范围。运行时间:如果编译器内联,则为O(0),O(1)否则。

描述

其实例可使用LValue调用的函数对象适配器模板和RValue参数。所有参数都是以引用到常量类型转发的L值,参考包装器除外,这些参考包装器已展开并可能产生非测试L值。

arity可以作为第二个数字非类型模板参数来限制转发到特定arity。如果是第三个数字非类型模板参数则第二个和第三个模板参数被视为最小值和最大arity。指定arity有助于改进诊断消息的可读性和编译时性能。

促进。结果属于可用于确定特定调用表达式的结果类型。

标题
#包括 <促进/功能性的/轻型前进适配器.马力>
简介
命名空间 促进
{
    模板<  功能,
        整数 数量_或最小数量 = 未指明的, 整数 最大数量 = 未指明的 >
    结构 轻型前进适配器;
}

符号

F类

可能是常量限定的函数对象类型或其引用类型

(f)

可转换为的对象F类

传真

类型轻型前进适配器<F类>

的实例传真,用初始化(f)

a0...澳大利亚

参数到

目标函数调用的结果类型必须为

促进::结果<F类*(技术顾问0 [常数]&...坦桑尼亚 [常数]&])>::类型

哪里技术顾问0...坦桑尼亚表示的参数类型a0...澳大利亚.

表达式语义学

表达式

语义学

传真((f))

创建适配器,用初始化目标函数(f).

传真()

创建适配器,尝试使用F类默认构造函数。

(a0...澳大利亚)

电话(f)带有常量参数a0...澳大利亚.如果人工智能是一个展开的引用包装。

限制

可以定义宏BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY设置最大调用arity。默认为10。

复杂性

预处理时间:O(N),其中N是arity极限。编译时间:O(N),其中N是调用的有效arity。运行时间:如果编译器为O(0)内联,否则为O(1)。

由于这些实用程序被排除在促进。融合功能模块,我想感谢Dan Marsden和Joel de Guzman让我首先参与了那座伟大图书馆的发展。

此外,我想赞扬以下参考文献的作者,因为他们的深入调查问题并在此实施解决方案。

最后,我要感谢维萨·卡诺文和保罗·门索尼德斯Boost预处理器库。没有它,我最终会得到一个这个的代码生成器。

  1. 这个转发问题彼得·迪莫夫(Peter Dimov)、霍华德·希南特(Howard E.Hinnant)、大卫·亚伯拉罕(David Abrahams)、,2002
  2. 促进。结果属于,Douglas Gregor,2004年
  3. 促进。裁判,贾科·贾维、彼得·迪莫夫、道格拉斯·格雷戈、大卫·亚伯拉罕斯,1999-2002年

上次修订时间:2008年11月1日19:58:50 GMT