62 votos

Debería al final el retorno de la sintaxis de tipo de estilo de convertirse en el predeterminado para los nuevos C++11 programas?

C++11 es compatible con una nueva sintaxis de la función:

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

En la actualidad esta función sería declarado como:

int func_name(int x, int y);

El nuevo estilo no parece ser ampliamente adoptado todavía (dicen que en el gcc stl)

Sin embargo, si este nuevo estilo de ser preferido en todas partes en el nuevo C++11-programas, o será sólo se utiliza cuando es necesario?

Personalmente, prefiero el antiguo estilo cuando sea posible, pero una base de código con una mezcla de estilos se ve bastante feo.

78voto

James McNellis Puntos 193607

Hay ciertos casos en los que usted debe utilizar un trailing tipo de retorno. Más en particular, una expresión lambda tipo de retorno, si se especifica, debe ser especificado a través de un trailing tipo de retorno. También, si su tipo de retorno utiliza un decltype que requiere que los nombres de los argumentos están en el ámbito, un final tipo de retorno debe ser utilizado (sin embargo, uno normalmente puede utilizar declval<T> a trabajar en torno a esta última cuestión).

Al final el tipo de retorno tiene algunas otras pequeñas ventajas. Por ejemplo, considere la posibilidad de un no en línea de definición de función miembro con el tradicional sintaxis de la funció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
{
    // ...
}

Miembro typedefs no están en el alcance hasta después de que el nombre de la clase aparece antes de ::get_integers, por lo que tenemos que repetir la clase de calificación de dos veces. Si vamos a utilizar un trailing tipo de retorno, no necesitamos repetir el nombre del tipo:

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

En este ejemplo, no es gran cosa, pero si usted tiene el tiempo, los nombres de clases o funciones miembro de la clase de plantillas que no están definidas en línea, entonces se puede hacer una gran diferencia en la legibilidad.

En su "Pintura Fresca" de la sesión en C++Ahora De 2012, Alisdair Meredith señaló que si el uso de trailing tipos de retorno de manera consistente, los nombres de todas sus funciones se alinean perfectamente:

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

He usado trailing tipos de devolución en todas partes en CxxReflect, así que si usted está buscando para obtener un ejemplo de código se ve el uso de ellos de manera consistente, usted puede tomar un vistazo aquí (e.g, el type de la clase).

53voto

Además de lo que otros han dicho, al final el tipo de retorno permite también usar this, lo cual no es permitido

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

En la segunda declaración, utilizamos el estilo tradicional. Sin embargo, desde this no está permitido en esa posición, el compilador no implícitamente el uso de la misma. Por lo que el a.end() utiliza la estáticamente tipo declarado de a para determinar qué end de sobrecarga de vector<int> va a llamar, que termina siendo el no-const versión.

7voto

PiotrNycz Puntos 8145

Vea este interesante artículo: http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html Muy buen ejemplo al utilizar esta sintaxis sin decltype en el juego:

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

Y brillante explicación también robado de Alex Allain del artículo "Debido a que el valor de retorno va al final de la función, en lugar de antes, no es necesario agregar el ámbito de la clase."

Comparar a este posible caso cuando por accidente se olvide sobre el ámbito de la clase, y, para los más grandes desastres, otro PersonType se define en el ámbito global:

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

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X