c++ - tipos - paso de parametros por referencia en c
¿Por qué se permite un paquete de parámetros después de los argumentos predeterminados? (3)
Como una adición a la gran respuesta de rsp, también vale la pena señalar que este comportamiento tiene un sentido lógico. Los argumentos no predeterminados, que no son paquetes de parámetros no pueden seguir a un argumento predeterminado sin resultar en el requisito de que el argumento predeterminado debe especificarse, en cuyo caso ya no es un argumento predeterminado.
Por ejemplo, si se permitiera lo siguiente:
void example(int x=0, int y);
El segundo argumento no predeterminado significaría que una llamada a la función tendría que ser un example(1, 2);
estructurado example(1, 2);
como el primer parámetro no puede ser por defecto. Este no es el caso para un paquete de parámetros vacío. Considera la siguiente función:
template <typename... T> void example(int x = 0, T&&... t);
En este caso, todavía es posible predeterminar x
llamando a example();
Tal vez me esté perdiendo algo obvio, pero lo siguiente se compila y se ejecuta, y no estoy seguro de por qué. Soy consciente de this , pero en el siguiente ejemplo, la posición del paquete de parámetros y el argumento predeterminado están invertidos. ¿No viola la regla de que los argumentos predeterminados deben aparecer en último lugar? El paquete de parámetros no puede tener un valor predeterminado.
#include <iostream>
#include <string>
#include <tuple>
template<typename ... Ts>
struct Test
{
int i;
std::string str;
Test(int _i = 0, Ts&& ... _ts)
:
i(_i),
str(std::get<0>(std::forward_as_tuple(std::forward<Ts>(_ts)...)))
{}
};
int main()
{
Test<std::string> t(1, "huh??");
std::cout << "t.i = " << t.i << ", t.str = " << t.str << "/n";
return 0;
}
Esto produce
t.i = 1, t.str = huh??
El porqué de esto es simple. Los paquetes de parámetros efectivos siempre tienen un valor predeterminado: los paquetes de parámetros pueden estar vacíos, por lo que no contradecirán el concepto de que los valores predeterminados faltantes deben ser los últimos argumentos.
Desde 8.3.6 ([dcl.fct.default]) / 4:
Para funciones que no son de plantilla, los argumentos predeterminados se pueden agregar en declaraciones posteriores de una función en el mismo ámbito. Las declaraciones en diferentes ámbitos tienen conjuntos completamente distintos de argumentos predeterminados. Es decir, las declaraciones en ámbitos internos no adquieren argumentos predeterminados de las declaraciones en ámbitos externos, y viceversa. En una declaración de función dada, cada parámetro posterior a un parámetro con un argumento predeterminado tendrá un argumento predeterminado suministrado en esta o una declaración anterior o será un paquete de parámetros de función. Un argumento por defecto no será redefinido por una declaración posterior (ni siquiera al mismo valor). [Ejemplo:
void g(int = 0, ...); // OK, ellipsis is not a parameter. So it can follow a parameter with a default argument