尾随返回类型语法样式是否应该成为新 C++11 程序的默认设置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11215227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:57:06  来源:igfitidea点击:

Should the trailing return type syntax style become the default for new C++11 programs?

c++c++11autotrailing-return-type

提问by mirk

C++11 supports a new function syntax:

C++11 支持新的函数语法:

auto func_name(int x, int y) -> int;

Currently this function would be declared as:

目前这个函数将被声明为:

int func_name(int x, int y);

The new style does not seem to be widely adopted yet (say in the gcc stl)

新样式似乎还没有被广泛采用(比如在 gcc stl 中)

However, should this new style be preferred everywhere in new C++11-programs, or will it only be used when needed?

然而,这种新风格是否应该在新的 C++11 程序中随处可见,还是只在需要时使用?

Personally, I prefer the old style when possible, but a code-base with mixed styles looks pretty ugly.

就我个人而言,如果可能的话,我更喜欢旧风格,但混合风格的代码库看起来很丑陋。

回答by James McNellis

There are certain cases where you must use a trailing return type. Most notably, a lambda return type, if specified, must be specified via a trailing return type. Also, if your return type utilizes a decltypethat requires that the argument names are in scope, a trailing return type must be used (however, one can usually use declval<T>to work around this latter issue).

在某些情况下,您必须使用尾随返回类型。最值得注意的是,如果指定了 lambda 返回类型,则必须通过尾随返回类型指定。此外,如果您的返回类型使用 adecltype要求参数名称在范围内,则必须使用尾随返回类型(但是,通常可以使用declval<T>来解决后一个问题)。

The trailing return type does have some other minor advantages. For example, consider a non-inline member function definition using the traditional function syntax:

尾随返回类型确实有一些其他的小优势。例如,考虑使用传统函数语法的非内联成员函数定义:

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
{
    // ...
}

Member typedefs are not in scope until after the name of the class appears before ::get_integers, so we have to repeat the class qualification twice. If we use a trailing return type, we don't need to repeat the name of the type:

成员 typedef 直到类名出现在 之前才在作用域内::get_integers,因此我们必须重复两次类限定。如果我们使用尾随返回类型,我们不需要重复类型的名称:

auto my_awesome_type::get_integers() const -> integer_sequence
{
    // ...
}

In this example, it's not such a big deal, but if you have long class names or member functions of class templates that are not defined inline, then it can make a big difference in readability.

在这个例子中,这没什么大不了的,但是如果你有很长的类名或类模板的成员函数没有内联定义,那么它可以在可读性上产生很大的不同。

In his "Fresh Paint"session at C++Now 2012, Alisdair Meredith pointed out that if you use trailing return types consistently, the names of all of your functions line up neatly:

在C++Now 2012 的“Fresh Paint”会议中,Alisdair Meredith 指出,如果您始终如一地使用尾随返回类型,则所有函数的名称都会整齐排列:

auto foo() -> int;
auto bar() -> really_long_typedef_name;

I've used trailing return types everywhere in CxxReflect, so if you're looking for an example of how code looks using them consistently, you can take a look there (e.g, the typeclass).

我到处使用后返回类型在CxxReflect,所以如果你正在寻找如何利用他们的代码看起来一致的例子,你可以看看那里(例如,type)。

回答by Johannes Schaub - litb

In addition to what others said, the trailing return type also allows to use this, which is not otherwise allowed

除了其他人所说的,尾随返回类型也允许使用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(); }
};

In the second declaration, we used the traditional style. However since thisis not allowed at that position, the compiler does not implicitly use it. So the a.end()uses the statically declared type of ato determine what endoverload of vector<int>it is going to call, which ends up being the non-const version.

在第二个声明中,我们使用了传统样式。但是,由于this在该位置不允许,编译器不会隐式使用它。所以a.end()使用静态声明的类型a来确定它要调用的end重载,vector<int>最终是非常量版本。

回答by s3rvac

Another advantage is that the trailing-return-type syntax can be more readable when the function returns a pointer to a function. For example, compare

另一个优点是,当函数返回一个指向函数的指针时,尾随返回类型语法可以更具可读性。例如,比较

void (*get_func_on(int i))(int);

with

auto get_func_on(int i) -> void (*)(int);

However, one can argue that better readability can be achieved simply by introducing a type alias for the function pointer:

然而,人们可能会争辩说,只需为函数指针引入一个类型别名就可以实现更好的可读性:

using FuncPtr = void (*)(int);
FuncPtr get_func_on(int i);

回答by PiotrNycz

See this nice article: http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.htmlVery good example when to use this syntax without decltype in game:

请参阅这篇不错的文章: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;
}

And brilliant explanation also stolen from Alex Allain's article "Because the return value goes at the end of the function, instead of before it, you don't need to add the class scope."

并且从 Alex Allain 的文章“因为返回值在函数的末尾而不是在它之前,您不需要添加类作用域”中也窃取了精彩的解释。

Compare to this possible case when one by accident forget about class scope, and, for bigger disaster, another PersonType is defined in global scope:

与这种可能的情况相比,当一个人不小心忘记了类作用域,并且对于更大的灾难,在全局作用域中定义了另一个 PersonType:

typedef float PersonType; // just for even more trouble
/*missing: Person::*/
PersonType Person::getPersonType ()
{
    return _person_type;
}