¿Debería el estilo de sintaxis del tipo de retorno final convertirse en el predeterminado para los nuevos programas C++11? [cerrado]

Resuelto mirk asked hace 12 años • 4 respuestas

C++ 11 admite una nueva sintaxis de función:

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

Actualmente esta función se declararía como:

int func_name(int x, int y);

El nuevo estilo no parece haber sido adoptado ampliamente todavía (por ejemplo, en gcc stl)

Sin embargo, ¿debería preferirse este nuevo estilo en todos los nuevos programas C++ 11, o sólo se utilizará cuando sea necesario?

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

mirk avatar Jun 27 '12 03:06 mirk
Aceptado

Hay ciertos casos en los que debe utilizar un tipo de retorno final. En particular, un tipo de retorno lambda, si se especifica, debe especificarse mediante un tipo de retorno final. Además, si su tipo de retorno utiliza un decltypeque requiere que los nombres de los argumentos estén dentro del alcance, se debe usar un tipo de retorno final (sin embargo, generalmente se puede usar declval<T>para solucionar este último problema).

El tipo de retorno final tiene algunas otras ventajas menores. Por ejemplo, considere una definición de función miembro no en línea utilizando la sintaxis de función tradicional:

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

Las definiciones de tipos de miembros no están dentro del alcance hasta que el nombre de la clase aparece antes ::get_integers, por lo que tenemos que repetir la calificación de la clase dos veces. Si utilizamos un tipo de retorno final, 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 tiene nombres de clase largos o funciones miembro de plantillas de clase que no están definidas en línea, entonces puede marcar una gran diferencia en la legibilidad.

En su sesión "Fresh Paint" en C++Now 2012, Alisdair Meredith señaló que si usa tipos de retorno finales de manera consistente, los nombres de todas sus funciones se alinean perfectamente:

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

He usado tipos de retorno finales en todas partes en CxxReflect , por lo que si está buscando un ejemplo de cómo se ve el código usándolos de manera consistente, puede echar un vistazo allí (por ejemplo, la typeclase ).

James McNellis avatar Jun 26 '2012 20:06 James McNellis

Además de lo que otros dijeron, el tipo de retorno final también permite el uso this, que de otro modo no está 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, dado que thisno está permitido en esa posición, el compilador no lo usa implícitamente. Entonces a.end()usa el tipo declarado estáticamente apara determinar qué endsobrecarga vector<int>va a llamar, que termina siendo la versión no constante.

Johannes Schaub - litb avatar Jun 27 '2012 21:06 Johannes Schaub - litb

Otra ventaja es que la sintaxis de tipo retorno final puede ser más legible cuando la función devuelve un puntero a una función. Por ejemplo, comparar

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

con

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

Sin embargo, se puede argumentar que se puede lograr una mejor legibilidad simplemente introduciendo un alias de tipo para el puntero de función:

using FuncPtr = void (*)(int);
FuncPtr get_func_on(int i);
s3rvac avatar Jan 12 '2017 15:01 s3rvac