Creo que las definiciones de las plantillas son incorrectas, en ambos casos está activando la recursión exacta. Yo habría esperado que el compilador para que con un poco de stackoverflow dentro del compilador, pero se produce un error diferente ...
Una implementación de la plantilla variadic are_same
podría ser:
template <class... Args> // base (optional to declare the template)
struct are_same;
template <class A, class B, class... Args> // recursion
struct are_same<A,B,Args...> {
static const bool value = is_same<A,B>::value && are_same<A,Args...>::value;
};
template <class A, class B> // stop condition
struct are_same<A,B> {
static const bool value = is_same<A,B>::value;
};
Tenga en cuenta que en el paso recursion
, se quita un argumento de la lista de argumentos, de modo que el nuevo problema que se resolverá es una versión reducida de del original. Este tipo de metaprogramación de plantillas está bastante relacionada con la recursión, y se aplican las mismas reglas, para poder utilizar la recursión debe asegurarse de que cada paso recursivo lo acerque a una solución. En este caso particular, dada una lista de N tipos potencialmente iguales, cada paso reduce el problema para encontrar si los tipos N-1 son los mismos.
Se puede utilizar alternativamente, como condición de parada (en sustitución de la anterior) una versión degenerada del problema are_same
:
template <class A>
struct are_same<A> {
static const bool value = true;
};
Cuál es degenerada en el sentido de que no tiene mucho sentido preguntar si un solo tipo * are_same *, pero para diferentes tareas de metaprogramación podría ser apropiado.
Un algoritmo potencialmente más eficiente diferente (no estoy seguro de si el compilador evitará la creación de instancias de la plantilla en el paso de recursión arriba) que no depende de is_same
podría ser:
template <class... Args>
struct are_same;
template <class A, class... Args>
struct are_same<A,A,Args...> { // recursion
static const bool value = are_same<A,Args...>::value;
};
template <class A, class B, class... Args>
struct are_same<A,B,Args...> { // cut, A and B are not the same
static const bool value = false;
};
template <class A>
struct are_same<A> { // end of recursion
static const bool value = true;
};
En este caso , el compilador preferirá los pasos recursion
a cut
cuando los dos tipos sean iguales, por lo que no es necesario que verifique is_same
internamente. Al mismo tiempo, si el compilador entra en el paso cut
, no es necesario que procesemos el resto de la lista de tipos, ya que ya conocemos la respuesta.
que está volviendo loco brillante, especialmente el "cortocircuito" paso. Gracias. – smallB
Bueno, pero hay un pequeño error en el primer fragmento de código. Debe ser 'static const bool value = is_same :: value && are_same :: value;' –
@VJo: Son exactamente iguales, una vez que se ha probado que 'A == B', recurrente con' 'o' 'no importa en absoluto, ni tendrá ninguna ventaja, que está provocando una nueva instancia de la plantilla y que en este momento el compilador va a resolver para cualquiera que sea el tipo de' A' y 'B' es (es decir, 'int ',' double' ...), ambos pedazos de código son exactamente iguales. –