Porque é que esta classe C ++ não é equivalente a este modelo?

votos
0

Alguém pode me explicar por que as seguintes obras:

template<class T> class MyTemplateClass {
public:
    T * ptr;
};

int main(int argc, char** argv) {
    MyTemplateClass<double[5]> a;
    a.ptr = new double[10][5];
    a.ptr[2][3] = 7;
    printf(%g\n, a.ptr[2][3]);
    return 0;
}

Mas isso não faz:

class MyClass {
public:
    double[5] * ptr;
    // double(*ptr)[5]; // This would work
};

int main(int argc, char** argv) {
    MyClass a;
    a.ptr = new double[10][5];
    a.ptr[2][3] = 7;
    printf(%g\n, a.ptr[2][3]);
    return 0;
}

há uma explicação simples desta magia - Obviamente há mais a instanciação de modelo do que apenas uma substituição textual pelos argumentos para o modelo?

Para este último o compilador (g ++ 4.1.2) expelir o seguinte erro:

test.cxx:13: error: expected unqualified-id before '[' token

Onde a linha 13 é a double[5] * ptr;linha.

A questão não é:

Por que o exemplo MyClass falhar? - porque C ++ não permite declarações de matriz estilo Java ;-).

Mas é:

Por que o exemplo MyTemplateClass ter sucesso?

Publicado 19/05/2009 em 17:10
fonte usuário
Em outras línguas...                            


3 respostas

votos
9

A diferença reside na gramática C ++. A simples declaração é formada assim:

declaration-specifier-seq init-declarator-list

Onde declaração-especificador-seq é uma sequência de especificadores de declaração:

simple-type-specifier: int, bool, unsigned, typedef-name, class-name ...
class-specifiers: class X { ... }
type-qualifier: const, volatile
function-specifier: inline, virtual, ... 
storage-class-specifier: extern, static, ...
typedef

Você entendeu a ideia. E init-declarator-lista é uma lista de declarators com um inicializador opcional para cada um:

a
*a
a[N]
a()
&a = someObj

Assim, uma simples declaração completa poderia ser semelhante a este, contendo 3 declarators:

int a, &b = a, c[3] = { 1, 2, 3 };

Os membros da classe têm regras especiais para dar conta do contexto diferente em que eles aparecem, mas eles são muito semelhantes. Agora, você pode fazer

typedef int A[3];
A *a;

Desde que o primeiro usa o especificador typedef e simples do tipo especificador e, em seguida, um declarator como "um [N]". A segunda declaração, em seguida, usa o typedef-name "A" (-type-especificador simples) e, em seguida, um declarator como "* a". No entanto, é claro que você não pode fazer

int[3] * a;

Uma vez que "int [3]" não é uma declaração-especificador-seq válida como mostrado acima.

E agora, naturalmente, um modelo é não apenas como uma substituição de texto macro. Um parâmetro de tipo de modelo, claro, é tratado como qualquer outro nome-tipo que é interpretado como apenas o tipo nomeia e pode aparecer onde um simples tipo especificador pode aparecer. Algumas C # pessoas tendem a dizer modelos C ++ são "apenas como macros", mas é claro que eles não são :)

Respondeu 19/05/2009 em 17:30
fonte usuário

votos
3
template<class T> MyTemplateClass {
    ...
}

está mais perto de

template<class T> MyTemplateClass {
    typedef {actual type} T;
    ...
}

do que uma substituição de texto simples.

Respondeu 19/05/2009 em 17:15
fonte usuário

votos
0

Existe uma diferença entre a utilização de um ponteiro ou matriz de ponteiros. Há uma necessidade de alocação de memória para cada elemento da sua matriz antes você está indo para usá-lo, e sim você tem um erro de digitação no segundo exemplo, você não definida modelo.

Respondeu 19/05/2009 em 17:18
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more