101

C ++ 11は、新しい関数構文をサポートしています。

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

現在、この関数は次のように宣言されます。

int func_name(int x, int y);

新しいスタイルはまだ広く採用されていないようです(たとえばgcc stlで)

ただし、この新しいスタイルは、新しいC ++ 11プログラムのどこでも優先する必要がありますか、それとも必要な場合にのみ使用しますか?

個人的には、可能な限り古いスタイルを好みますが、スタイルが混在するコードベースはかなり醜いように見えます。

4

4 に答える 4

120

末尾の戻り値の型を使用する必要がある特定のケースがあります。特に、ラムダの戻り値の型を指定する場合は、末尾の戻り値の型を介して指定する必要があります。また、戻り値の型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に表示されるまでスコープに含まれないため、クラス修飾を 2 回繰り返す必要があります。末尾の戻り型を使用する場合、型の名前を繰り返す必要はありません。

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)を参照してください。

于 2012-06-26T20:28:01.470 に答える
70

他の人が言ったことに加えて、トレーリングリターンタイプは、他の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(); }
};

2番目の宣言では、従来のスタイルを使用しました。ただし、thisその位置では許可されていないため、コンパイラーは暗黙的にそれを使用しません。したがって、a.end()は静的に宣言されたタイプを使用して、aどのendオーバーロードがvector<int>呼び出されるかを決定します。これは、最終的に非constバージョンになります。

于 2012-06-27T21:44:39.610 に答える
10

この素晴らしい記事を参照してください: 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;
}
于 2012-06-26T20:38:24.063 に答える