Una buena razón podría ser que
void foo(bar, xyzzy = 0);
es similar a un par de sobrecargas.
void foo(bar b) { foo(b, 0); }
foo(bar, xyzzy);
Por otra parte, a veces es ventajoso refactorizar en tales:
void foo(bar b) { /* something other than foo(b, 0); */ }
foo(bar, xyzzy);
Incluso cuando se escribe como una sola, es todavía como dos funciones en uno, ninguno de los cuales es "preferido" en ningún sentido . Llamas a la función de un argumento; el de dos argumentos es efectivamente una función diferente. La notación de argumento predeterminada simplemente los fusiona en uno.
Si la sobrecarga tuviera el comportamiento que está solicitando, para coherencia tendría que funcionar en el caso cuando la plantilla se divide en dos definiciones. ¡Eso no tendría sentido porque entonces la deducción sería extraer tipos de una función no relacionada que no se está llamando! Y si no se implementara, significaría que la sobrecarga de diferentes longitudes de listas de parámetros se convierte en un "ciudadano de segunda clase" en comparación con "argumentos predeterminados".
Es bueno si la diferencia entre sobrecargas y valores predeterminados está completamente oculta para el cliente.
Si bien decir "Porque el estándar lo dice" es una respuesta válida, sería bueno saber el razonamiento detrás de esto. –
Entre otras razones, diferentes declaraciones de una función pueden declarar diferentes argumentos predeterminados (estoy bastante seguro de que lo mismo se aplica a las plantillas de función). –
@Juegos: No, las declaraciones diferentes no pueden declarar diferentes argumentos predeterminados. Ni siquiera está permitido que múltiples declaraciones den el mismo valor predeterminado al mismo argumento. 8.3.6 dice "Un argumento predeterminado no será redefinido por una declaración posterior (ni siquiera al mismo valor)". Por supuesto, eso solo se aplica a las funciones que no son de plantilla. Para funciones de plantilla, parece que los argumentos predeterminados solo se pueden proporcionar en la declaración inicial. –