Pregunta

Un amigo y yo estábamos hablando de plantillas de C++.Me preguntó qué debería hacer esto:

#include <iostream>

template <bool>
struct A {
    A(bool) { std::cout << "bool\n"; }
    A(void*) { std::cout << "void*\n"; }
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new A< b > (c) > (d);
}

La última línea de main tiene dos análisis razonables.¿Es 'b' el argumento de la plantilla o es b > (c) el argumento de la plantilla?

Aunque es trivial compilar esto y ver qué obtenemos, nos preguntamos qué resuelve la ambigüedad.

¿Fue útil?

Solución

AFAIK se compilaría como new A<b>(c) > d.Esta es la única forma razonable de analizarlo en mi humilde opinión.Si el analizador no puede asumir en circunstancias normales un argumento > final de una plantilla, eso resultaría en mucha más ambigüedad.Si lo quieres al revés, deberías haber escrito:

new A<(b > c)>(d);

Otros consejos

Como indica Leon & Lee, 14.2/3 (C++ '03) define explícitamente este comportamiento.

C++ '0x aumenta la diversión con una regla similar que se aplica a >>.El concepto básico es que al analizar una lista de argumentos de plantilla, una lista de argumentos no anidada >> serán tratados como dos distintos > > tokens y no el operador de turno correcto:

template <bool>
struct A {
  A(bool);
  A(void*);
};

template <typename T>
class C
{
public:
  C (int);
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new C <A< b  >>  (c) > (d); // #1
    new C <A< b > >  (c) > (d); // #2
}

'#1' y '#2' son equivalentes en lo anterior.

Por supuesto, esto soluciona la molestia de tener que agregar espacios en especializaciones anidadas:

C<A<false>> c;  // Parse error in C++ '98, '03 due to "right shift operator"

El estándar C++ define que si para un nombre de plantilla seguido de un <, el < es siempre el comienzo de la lista de argumentos de la plantilla y el primer no anidado > se toma como el final de la lista de argumentos de la plantilla.

Si pretendía que el resultado de la > operador sea el argumento de la plantilla, entonces deberá encerrar la expresión entre paréntesis.No necesitas paréntesis si el argumento era parte de un static_cast<> u otra expresión de plantilla.

La avidez del léxer es probablemente el factor determinante a falta de paréntesis para hacerlo explícito.Supongo que el Lexer no es codicioso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top