c++ - studio - El paquete de parámetros debe estar al final de la lista de parámetros... ¿Cuándo y por qué?
taglib java (2)
El primero no está bien. El compilador es simplemente defectuoso y no pudo diagnosticarlo. [temp.param]/11 :
Un paquete de parámetros de plantilla de una función no debe ir seguido de otro parámetro de plantilla a menos que ese parámetro de plantilla pueda deducirse de la lista de tipos de parámetros de la plantilla de función o tenga un argumento predeterminado (14.8.2).
Si el tipo de función T(Args...)
es significativo para el usuario final, una forma de solucionarlo sería utilizar una especialización parcial en su lugar:
template<class F, class Alloc> class C; //undefined
template<class T, class... Args, class Alloc>
class C<T(Args...), Alloc> {
// implementation
};
Dependiendo de los requisitos reales, también podría valer la pena considerar la eliminación de tipos del asignador.
No entiendo la razón por la cual un paquete de parámetros debe estar al final de la lista de parámetros si esta última está vinculada a una clase, mientras que la restricción se relaja si la lista de parámetros es parte de una declaración de método de miembro.
En otros términos, éste compila:
class C {
template<typename T, typename... Args, typename S>
void fn() { }
};
El siguiente no lo hace:
template<typename T, typename... Args, typename S>
class C { };
¿Por qué el primer caso se considera correcto y el segundo no?
Quiero decir, si es una sintaxis legal, ¿no debería serlo en ambos casos?
Para ser claro, el problema real es que estaba definiendo una clase similar a la siguiente:
template<typename T, typename... Args, typename Allocator>
class C { };
Se agradecería tener el tipo de asignador como último tipo, pero puedo solucionarlo de alguna manera (de todos modos, si tiene una sugerencia, se agradece, ¡¡tal vez la suya sea mucho más elegante que la mía !!).
Dicho esto, me salió el error:
el paquete de parámetros ''Args'' debe estar al final de la lista de parámetros de la plantilla
Entonces, solo tenía curiosidad por entender completamente por qué se acepta en algunos casos, pero no en otros.
Here hay una pregunta similar, pero simplemente explica cómo resolver el problema y eso fue bastante claro para mí.
Es válido para las plantillas de función, pero solo cuando la deducción de argumentos puede ayudar al compilador a resolver los parámetros de la plantilla, tal como está, su ejemplo de plantilla de función es prácticamente inútil porque
template<typename T, typename... Args, typename S> void fn() { }
int main() { fn<int, int, int>(); }
test.cpp: In function ''int main()'':
test.cpp:2:32: error: no matching function for call to ''fn()''
int main() { fn<int, int, int>(); }
^
test.cpp:1:57: note: candidate: template<class T, class ... Args, class S> void fn()
template<typename T, typename... Args, typename S> void fn() { }
^
test.cpp:1:57: note: template argument deduction/substitution failed:
test.cpp:2:32: note: couldn''t deduce template parameter ''S''
int main() { fn<int, int, int>(); }
el compilador no tiene manera de determinar qué parámetros de la plantilla pertenecen al paquete de parámetros, y cuáles a S
De hecho, como @TC señala, en realidad debería ser un error de sintaxis porque una plantilla de función definida de esta manera nunca puede ser instanciada.
Una plantilla de función más útil sería algo así como
template<typename T, typename... Args, typename S> void fn(S s) { }
como ahora el compilador es capaz de hacer coincidir de manera inequívoca los parámetros de función s
con el tipo de plantilla S
, con el efecto secundario de que siempre se deducirá S
: todos los parámetros explícitos de la plantilla después del primero pertenecerán a Args
.
Nada de esto funciona para las plantillas de clase (primaria), los parámetros no se deducen y está expresamente prohibido:
Del proyecto n4567.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf
[temp.param] / 11
[...] Si un parámetro de plantilla de una plantilla de clase primaria o plantilla de alias es un paquete de parámetros de plantilla, será el último parámetro de plantilla . [...]
(Si se deducieran, sería ambiguo como en el ejemplo de la plantilla de función).