C++11 支持一种新的函数语法:
auto func_name(int x, int y) -> int;
目前这个函数将被声明为:
int func_name(int x, int y);
新风格似乎还没有被广泛采用(比如在 gcc stl 中)
然而,这种新风格应该在新的 C++11 程序中无处不在,还是只在需要时使用?
就个人而言,如果可能的话,我更喜欢旧风格,但是混合风格的代码库看起来很丑。
C++11 支持一种新的函数语法:
auto func_name(int x, int y) -> int;
目前这个函数将被声明为:
int func_name(int x, int y);
新风格似乎还没有被广泛采用(比如在 gcc stl 中)
然而,这种新风格应该在新的 C++11 程序中无处不在,还是只在需要时使用?
就个人而言,如果可能的话,我更喜欢旧风格,但是混合风格的代码库看起来很丑。
在某些情况下,您必须使用尾随返回类型。最值得注意的是,如果指定了 lambda 返回类型,则必须通过尾随返回类型指定。此外,如果您的返回类型使用decltype
要求参数名称在范围内的 a,则必须使用尾随返回类型(但是,通常可以使用declval<T>
来解决后一个问题)。
尾随返回类型确实有一些其他的小优势。例如,考虑使用传统函数语法的非内联成员函数定义:
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
{
// ...
}
成员 typedef 直到类名出现之前才在范围内::get_integers
,因此我们必须重复两次类限定。如果我们使用尾随返回类型,我们不需要重复类型的名称:
auto my_awesome_type::get_integers() const -> integer_sequence
{
// ...
}
在这个例子中,这没什么大不了的,但是如果你有很长的类名或类模板的成员函数没有内联定义,那么它可以在可读性上产生很大的不同。
Alisdair Meredith 在 C++Now 2012的“Fresh Paint”会议中指出,如果您始终使用尾随返回类型,则所有函数的名称都会整齐排列:
auto foo() -> int;
auto bar() -> really_long_typedef_name;
我在CxxReflect的任何地方都使用了尾随返回类型,因此,如果您正在寻找代码如何始终如一地使用它们的示例,您可以查看那里(例如,class type
)。
除了其他人说的,尾随返回类型还允许使用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
来确定将要调用end
的重载类型vector<int>
,最终成为非常量版本。
另一个优点是,当函数返回指向函数的指针时,尾随返回类型语法更具可读性。例如,比较
void (*get_func_on(int i))(int);
和
auto get_func_on(int i) -> void (*)(int);
但是,有人可以争辩说,只需为函数指针引入一个类型别名就可以实现更好的可读性:
using FuncPtr = void (*)(int);
FuncPtr get_func_on(int i);
请参阅这篇不错的文章: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 Alllain 的文章“因为返回值在函数的末尾,而不是在它之前,你不需要添加类范围”中也有精彩的解释。
与这种意外忘记类范围的可能情况相比,并且为了更大的灾难,在全局范围内定义了另一个 PersonType:
typedef float PersonType; // just for even more trouble
/*missing: Person::*/
PersonType Person::getPersonType ()
{
return _person_type;
}