企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 返回值类型后置语法 考虑下面这段代码: ``` template<class T, class U> ??? mul(T x, U y) { return x*y; } ``` 函数mul()的返回类型要怎么写呢?当然,是“x*y类型”,但是这并不是一个数据类型,我们如何才能一开始就得到它的真实数据类型呢?在初步了解C++0x之后,你可能一开始想到使用decltype来推断“x*y”的数据类型: ``` template<class T, class U> decltype(x*y) mul(T x, U y) // 注意这里的作用域 { return x*y; } ``` 但是,这种方式是行不通的,因为x和y不在作用域内。但是,我们可以这样写: ``` template<class T, class U> // 难看别扭,且容易产生错误 decltype(*(T*)(0)**(U*)(0)) mul(T x, U y) { return x*y; } ``` 如果称这种用法为“还可以”,就已经是过誉了。 C++11的解决办法是将返回类型放在它所属的函数名的后面: ``` template<class T, class U> auto mul(T x, U y) -> decltype(x*y) { return x*y; } ``` 这里我们使用了auto关键字,(auto在C++11中还有根据初始值推导数据类型的意义),在这里它的意思变为“返回类型将会稍后引出或指定”。 返回值后置语法最初并不是用于模板和返回值类型推导的,它实际是用于解决作用域问题的。 ``` struct List { struct Link { /* ... */ }; Link* erase(Link* p); // 移除p并返回p之前的链接 // ... }; List::Link* List::erase(Link* p) { /* ... */ } ``` 第一个List::是必需的,这仅是因为List的作用域直到第二个List::才有效。更好的表示方式是: ``` auto List::erase(Link* p) -> Link* { /* ... */ } ``` 现在,将函数返回类型后置,Link*就不需要使用明确的List::进行限定了。 参考: * the C++ draft section ??? * [Str02] Bjarne Stroustrup. Draft proposal for “typeof”. C++ reflector message c++std-ext-5364, October 2002. * [N1478=03-0061] Jaakko Jarvi, Bjarne Stroustrup, Douglas Gregor, and Jeremy Siek: [Decltype and auto](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1478.pdf). * [N2445=07-0315] Jason Merrill: [New Function Declarator Syntax Wording](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2445.html). * [N2825=09-0015] Lawrence Crowl and Alisdair Meredith: [Unified Function Syntax](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2825.html).