Pregunta

El siguiente código debe explicarse por sí misma. Tengo dos preguntas con respecto a la sintaxis utilizada (que es la línea que debe ser usado). Yo estaré siempre agradecido si usted podría proporcionar respuestas a estas preguntas presentadas.

template <typename T>
struct A {
    template <typename S>
    void f (const A<S> &s);

    template <typename S>
    friend struct A; 
    // Question 1: why isn't the syntax 'friend struct A<S>' ? 
    // The semantic would stay, since we would like A<S> (for ANY S) to be friend of every A<T>..

    private:
        void g () const {}
};

template <typename T> 
template <typename S> // Question 2: Why can't the syntax be 'template <typename T, typename S>' ?
void A<T>::f (const A<S> &s) {
    s.g();
}

int main () {
    A<bool> abool;
    A<char> achar;

    abool.f(achar);
}

He comprobado que, efectivamente, esto es únicamente la sintaxis correcta (voy a estar feliz de saber que me equivoque). Mis preguntas son más con respecto a la motivación de la sintaxis, como se explica en el cuerpo de las preguntas.

Gracias por cualquier ayuda.

¿Fue útil?

Solución

  

¿Por qué no es la sintaxis ...

     

¿Por qué no puede ser la sintaxis ...

¿Qué espera que digamos? Quien decidió esta sintaxis (en su mayoría BS sí mismo, que yo sepa) pensó que su sintaxis mejor que el suyo.

¿Cuál es mejor o más fácil de recordar que no sabría - pero yo no encontrar la suya haciendo más sentido que el suyo. Usted es libre de no estar de acuerdo, por supuesto.

Editar pregunta OK, Alexander ha respondido muy bien # 2 . Sobre nº 1:

La diferencia es que los nombres de A<S> un type , que es lo que se espera para un argumento de función, mientras que A por sí mismo es el nombre de un plantilla , de la que los tipos se van a crear, lo cual tiene sentido si quiere hacerse amigo de un plantilla en lugar de un tipo:

template <typename S>
void f (const A<S> &s); // A<S> being the name of a type

template <typename S>
friend struct A; // A being the name of a template

puede amigo de un modelo específico ejemplo en lugar de toda la plantilla, pero para que la plantilla ya debe ser conocido por el compilador (es decir, declarada) en el friend Declaración:

template< typename T >
class foo;

class bar {
  friend class foo<int>; // foo<int> being the name of a specific instance of foo
};

Así que hacerse amigo de un plantilla es una excepción (las declaraciones friend "habituales" declara una función o clase) y necesita la sintaxis diferente.

Otros consejos

Aunque no puedo decir ¿Por qué esta sintaxis fue escogido, sólo puedo decir que iba a apoyar tanto a las decisiones tomadas por los diseñadores del lenguaje - que tiene sentido para mí. En la pregunta 2, que tiene no sólo una plantilla, tiene dos niveles de plantillas anidadas. ¿Por qué la sintaxis para definir un miembro de la plantilla de una clase de plantilla ocultar este hecho? De esta manera, es sólo una re-combinación de sintaxis de la plantilla existente, mientras que el suyo requeriría reglas especiales para fusionar los argumentos de plantilla para las plantillas anidadas en una template<>.

Suponga que su declaración de plantilla anidada fueron sólo un poco más complicado:

template <typename T, int I>
struct A {
    template <typename S, I>
    void f (const A<S, I> &s);

    template <typename S, int J>
    friend struct A; 
    // Question 1: why isn't the syntax 'friend struct A<S, J>' ? 
    // The semantic would stay, since we would like A<S, J> (for ANY S, J combination) to be friend of every A<T, I>..

    private:
        void g () const {}
};

template <typename T, int I> 
template <typename S> // Question 2: Why can't the syntax be 'template <typename T, int I, typename S>' ?
void A<T>::f (const A<S> &s) {
    s.g();
}

int main () {
    A<bool, 5> abool;
    A<char, 7> achar;

    abool.f(achar);
}

De repente su sugerencia no parece tan razonable o evidente más. ¿Qué conjunto de argumentos va primero? Supongamos que se estaba utilizando C ++ 0x y tenía una lista de argumentos variable?

En cuanto a la declaración amigo, por tener la sintaxis que se propone (friend struct <S, J>), de repente hacer que el compilador tiene que deducir que S y J se ofrecen como argumentos de plantilla y no debe ser tomado a partir de un cierto margen al azar. Supongamos que alguien introdujo un tipo S al mismo nivel de evaluación como struct A? ¿Qué S sería la declaración friend struct A<S,J> refiere? ¿Cómo sabría el compilador? ¿Es razonable tiene la introducción de un nombre en un ámbito exterior para cambiar radicalmente el significado de una declaración en un ámbito anidado?

Y si nos referimos que la declaración debe decir, en total: template <typename S, int J> friend struct A<S, J>, entonces ¿por qué un amigo hacia adelante mirada declaración de plantilla diferente de una declaración de plantilla estándar? Es redundante incluir los nombres de las variables de la plantilla después de que el nombre de la plantilla cuando ya se les menciona en la parte template <typename S, int J>.

También cree que su sintaxis sugerido haría averiguar lo que una especialización de plantilla está haciendo mucho más difícil debido a que tendría que mirar a más partes del código y correlacionar las cosas.

A modo de ejemplo, una especialización de plantilla de mi versión de A se vería así:

template <typename T>
struct A<T, 5> {
};

Y como se puede ver, esto es extraño cerca de su amigo le sugirió sintaxis de declaración hacia adelante, y podría ser difícil saber si está o no está con la intención de especificar una versión especializada o no. Sería necesario hacer coincidir argumentos de plantilla con los parámetros de plantilla, mientras que en el camino se hace actualmente, si no tiene los parámetros de plantilla que no estamos hablando de una especialización.

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