Sondaki dönüş türü söz dizimi stili yeni C ++ 11 programları için varsayılan hale gelmeli mi? [kapalı]


92

C ++ 11, yeni bir işlev sözdizimini destekler:

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

Şu anda bu işlev şu şekilde ilan edilecektir:

int func_name(int x, int y);

Yeni stil henüz geniş çapta benimsenmiş görünmüyor (gcc stl'de diyelim)

Ancak bu yeni stil, yeni C ++ 11 programlarında her yerde mi tercih edilmeli yoksa sadece ihtiyaç duyulduğunda mı kullanılacak?

Şahsen, mümkün olduğunda eski stili tercih ederim, ancak karışık stillere sahip bir kod tabanı oldukça çirkin görünüyor.


29
Çoğunlukla decltypetartışmalar için oradadır .
Cat Plus Plus

CatPlusPlus'ın söylediği: örneğinizde kullanmak pek mantıklı değil
stijn

@Cat Plus Plus Bu, dönüş türünü türetmeniz gerekmedikçe, şeyleri C ++ 03'teki gibi bırakmanız anlamına gelir?
mirk

1
Her işlevin önünde "otomatik" i belirtmek zorunda olmak çirkin. Bu C ++ 'ın python'un "def" cevabına verdiği müstehcen cevap gibi mi?
Erik Aronesty

Yanıtlar:


110

Sonda bir dönüş türü kullanmanız gereken belirli durumlar vardır. En önemlisi, bir lambda dönüş türü, belirtilirse, sondaki dönüş türü aracılığıyla belirtilmelidir. Ayrıca, dönüş türünüz decltype, bağımsız değişken adlarının kapsam içinde olmasını gerektiren a kullanıyorsa , sondaki dönüş türü kullanılmalıdır (ancak, genellikle declval<T>bu son soruna geçici bir çözüm bulmak için kullanılabilir ).

Sondaki dönüş türünün başka bazı küçük avantajları vardır. Örneğin, geleneksel işlev sözdizimini kullanan satır içi olmayan bir üye işlev tanımını düşünün:

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

Üye türleri, sınıfın adı daha önce görünene kadar kapsam dahilinde değildir ::get_integers, bu nedenle sınıf niteliğini iki kez tekrarlamamız gerekir. Sonda bir dönüş türü kullanırsak, türün adını tekrar etmemize gerek yoktur:

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

Bu örnekte, o kadar da önemli değil, ancak uzun sınıf adlarına veya satır içi tanımlanmamış sınıf şablonlarının üye işlevlerine sahipseniz, okunabilirlikte büyük bir fark yaratabilir.

Onun içinde "Taze Boya" C ++ Şimdi 2012'de de oturumda, Alisdair Meredith sürekli olarak dönüş türlerini sondaki kullanırsanız, tüm fonksiyonları isimleri düzgünce sıraya dikkat çekti:

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

Ben her yerde dönüş türlerini sondaki kullanılan ettik CxxReflect kod görünüyor sürekli bunları kullanarak nasıl bir örnek arıyorsanız eğer öyleyse, bir göz var (örneğin alabilir sınıf ).type


1
Henüz bir fikir birliği var gibi görünmüyor ancak CxxReflect'e yeni stille bakmak ilginç.
mirk

Merhaba James. Bu cevap muhtemelen C ++ 14 standardı ışığında daha doğru yapılabilir.
Drew Dormann

@DrewDormann Neyi eklersiniz / değiştirirsiniz?
underscore_d

Hizalama aslında büyük bir artı, dilediğim noktaya kadar burada anlamsız 'otomatik'in yerini alacak yeni bir' func 'anahtar sözcüğü olmasını diledim.
Johan Boulé

67

Başkalarının söylediklerine ek olarak, takip eden dönüş türü de kullanılmasına izin verir this, aksi halde izin verilmez

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(); }
};

İkinci bildiride geleneksel tarzı kullandık. Ancak bu thiskonumda izin verilmediğinden, derleyici onu örtük olarak kullanmaz. Bu nedenle, hangi aşırı a.end()yüklemenin çağrılacağını abelirlemek için statik olarak bildirilen türünü kullanır, bu da const olmayan sürüm olur.endvector<int>


2
Bu, kavramın iyi / düzgün bir gösterimi olsa da (dönüş türlerinde üyelerin kullanılması) komiktir, çünkü C ++ 14'te bir türün belirtilmesi, dönüştürme olmadan satır içi tanımda tamamen gereksizdir; artık tam dönüş türü kesintisini kullanabiliriz. : P
alt

27

Diğer bir avantaj, sondaki dönüş türü sözdiziminin, işlev bir işleve bir işaretçi döndürdüğünde daha okunabilir olmasıdır. Örneğin, karşılaştırın

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

ile

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

Bununla birlikte, daha iyi okunabilirliğin basitçe işlev işaretçisi için bir tür takma adı getirilerek elde edilebileceği iddia edilebilir:

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

10

Bu güzel makaleye bakın: http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html Bu sözdiziminin oyunda decltype olmadan ne zaman kullanılacağına çok iyi bir örnek :

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;
}

Ve harika bir açıklama da Alex Allain'in makalesinden çalındı, "Dönüş değeri fonksiyonun öncesine değil sonuna gittiğinden, sınıf kapsamını eklemenize gerek yok."

Birinin kazara sınıf kapsamını unuttuğu bu olası durumla karşılaştırın ve daha büyük felaketler için, küresel kapsamda başka bir PersonType tanımlanır:

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

7
Bunun "felaket" kategorisine girdiğinden emin değilim: tür yanlışsa, kod derlenmez. Çalışma zamanı hataları feci sonuçlara yol açabilir; derleme zamanı hataları, çok fazla değil.
James McNellis

4
@JamesMcNellis derleyici çıktısını karşılaştırır: prog.cpp:13:12: error: prototype for 'PersonType Person::getPersonType()' does not match any in class 'Person'vs. prog.cpp:13:1: error: 'PersonType' does not name a type Derleyiciden gelen ilk hata, en azından benim için anlaşılması daha kötü.
PiotrNycz

Şahsen ben katılmıyorum, ikinci mesajı okumayı daha zor buluyorum ve uygulamanın beyanname gibi görünmesini tercih ederim.
JRH
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.