尾部返回types语法样式应该成为新的C ++ 11程序的默认值?
C ++ 11支持一个新的函数语法:
auto func_name(int x, int y) -> int;
目前这个函数将被声明为:
int func_name(int x, int y);
新的风格似乎还没有被广泛采用(比如在gcc stl中)
但是,在新的C ++ 11程序中是否应该使用这种新的风格,还是只在需要时使用?
就个人而言,我更喜欢旧的风格,但一个混合风格的代码库看起来很丑。
在某些情况下,您必须使用尾随返回types。 最值得注意的是,如果指定了lambda返回types,则必须通过尾随返回types来指定。 另外,如果你的返回types使用一个decltype
,要求参数名称在范围内,则必须使用尾随返回types(但是,通常可以使用declval<T>
来解决后一个问题)。
尾随返回types有一些其他的小优点。 例如,考虑使用传统函数语法的非内联成员函数定义:
struct my_awesome_type { typedef std::vector<int> integer_sequence; integer_sequence get_integers() const; }; my_awesome_type::integer_sequence my_awesome_type::get_integers() const { // ... }
成员typedefs不在范围内,直到类的名称出现在::get_integers
之前,所以我们必须重复两次类的限定条件。 如果我们使用尾随返回types,我们不需要重复types的名称:
auto my_awesome_type::get_integers() const -> integer_sequence { // ... }
在这个例子中,这不是什么大不了的事,但是如果你有很长的类名或类模板的成员函数没有内联定义,那么它在可读性方面就会有很大的不同。
在C ++ Now 2012的“Fresh Paint”会议上,Alisdair Meredith指出,如果您始终使用尾随返回types,则所有函数的名称将整齐排列:
auto foo() -> int; auto bar() -> really_long_typedef_name;
我已经在CxxReflect中使用了尾随返回types,所以如果你正在寻找代码如何使用它们的例子,你可以看看那里(例如, type
类 )。
除了别人所说的,追尾返回types也允许使用this
,这是不允许的
struct A { std::vector<int> a; // OK, works as expected auto begin() const -> decltype(a.begin()) { return a.begin(); } // FAIL, does not work: "decltype(a.end())" will be "iterator", but // the return statement returns "const_iterator" decltype(a.end()) end() const { return a.end(); } };
在第二个宣言中,我们使用了传统风格。 但是,由于this
位置是不允许的,所以编译器不会隐式地使用它。 因此, a.end()
使用a的静态声明types来确定它将调用的vector<int>
哪个end
重载,最终是非const版本。
看看这个漂亮的文章: http : //www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html非常好的例子,当在游戏中使用这个没有decltype的语法:
class Person { public: enum PersonType { ADULT, CHILD, SENIOR }; void setPersonType (PersonType person_type); PersonType getPersonType (); private: PersonType _person_type; }; auto Person::getPersonType () -> PersonType { return _person_type; }
Alex Allain的文章“因为返回值在函数的末尾,而不是在它之前,你不需要添加类作用域”。
相比于这种可能出现的情况,如果偶然忘记了类作用域,而对于更大的灾难,则在全局作用域中定义另一个PersonType:
typedef float PersonType; // just for even more trouble /*missing: Person::*/ PersonType Person::getPersonType () { return _person_type; }
另一个优点是当函数返回一个指向函数的指针时,尾随返回types的语法可以更易读。 例如,比较
void (*get_func_on(int i))(int);
同
auto get_func_on(int i) -> void (*)(int);
然而,有人可能会争辩说,通过为函数指针引入一个types别名,可以实现更好的可读性:
using FuncPtr = void (*)(int); FuncPtr get_func_on(int i);