我遇到了以下代码:
template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) { return a+b; }
有一件事我不能理解
我可以在哪里找到箭头操作符(->)在函数标题中的含义?
->
我猜纯粹是逻辑上的,->操作符决定了一个类型,auto将被推导出来,但我想弄清楚这一点。我找不到任何信息。
auto
简单地说,它告诉返回类型是a和b的和的推断类型。
a
b
在c++ 11中,函数声明有两种语法:
,,, 返回类型 标识符 ( argument-declarations…… )
(
)
而且
,,, auto 标识符 ( argument-declarations…… ) -> return_type
它们是等价的。当它们相等时,为什么还要用后者呢?c++ 11引入了这个很酷的decltype东西,它允许你描述表达式的类型。你可能想从参数类型中派生返回类型。所以你试着:
decltype
template <typename T1, typename T2> decltype(a + b) compose(T1 a, T2 b);
编译器会告诉你它不知道a和b在decltype参数中是什么。这是因为它们只由参数列表声明。
你可以通过使用declval和已经声明的模板参数轻松解决这个问题。如:
declval
template <typename T1, typename T2> decltype(std::declval<T1>() + std::declval<T2>()) compose(T1 a, T2 b);
只是现在变得很啰嗦了。因此,提出并实现了替代声明语法,现在您可以编写
template <typename T1, typename T2> auto compose(T1 a, T2 b) -> decltype(a + b);
而且它不那么冗长,范围规则也不需要更改。
c++ 14日更新: c++ 14也允许
,,, auto 标识符 ( argument-declarations…… )
只要函数在使用前完全定义,并且所有return语句推导为相同的类型。如果你想在源文件中隐藏函数体,->语法对于公共函数(在头文件中声明)仍然很有用。显然,这不能用模板来完成,但是有一些具体的类型(通常通过模板元编程派生)很难用其他方法来编写。
return
除了decltype和declval用法外,还可以使用类中定义的返回类型定义类成员函数,而不需要第二次提供Class::作用域解析前缀。
Class::
例子:
class SomeLongClassname { public: typedef std::shared_ptr<Node> PNode; PNode make_node (); };
选择:
SomeLongClassname::PNode SomeLongClassname::make_node () { ... }
或
auto SomeLongClassname::make_node () -> PNode { ... }
第二种形式有时更容易辨认。