Os modelos C ++ são apenas um tipo de macros glorificadas?


27

De diferentes comparações entre modelos C ++ e genéricos C # / Java como este

/programming/31693/what-are-the-differences-between-generics-in-c-and-java-and-templates-in-c/31929#31929

Percebi que os modelos C ++ são implementados por algum tipo de pré-processamento (substituição de texto sem formatação antes da análise), não compilando. Porque a verificação de tipo nos modelos C ++ é semelhante às macros C. Quero dizer, se houver alguns erros, eles são erros do código gerado após o processamento de blocos de código modelados, não dos próprios modelos. Em outras palavras, eles são apenas um tipo de versão superior de macros em C.

Então eu encontrei alguns outros fatos que apóiam isso -

  • Eu pensei que, se os modelos de C ++ forem implementados por pré-processamento, haverá problemas com o vínculo dinâmico (usando .dll). E uma pesquisa rápida apoiou isso.

  • Outro ponto é que constantes inteiras podem ser passadas como argumentos para os modelos. E ainda suporta algum tipo de recursão. Mas essa recursão não é encontrada no código de montagem / máquina compilado. A coisa da recursão é gerenciada em tempo de compilação, gerando funções para cada chamada recursiva e, portanto, tendo um binário executável maior, mas mais rápido.

Embora diferente das macros C, ele possui algumas habilidades superiores. Mas o modelo C ++ não é implementado com algum tipo de pré-processamento? Como isso é implementado em diferentes compiladores C ++?


19
Não. Modelos C ++ são compilados.
Edward Strange

2
Qual é a sua definição de "pré-processamento"? E de "compilar"? Uma definição suficientemente ampla de "pré-processamento" pode incluir tudo o que um compilador faz; afinal, um compilador realmente processa a fonte antes de ser executada, não?
James McNellis

@ James McNellis IMHO Se você puder apenas diferenciar o pré-processamento de todas as outras coisas feitas para a compilação, basta entender minha pergunta. Para esclarecer o pré-processador
Gulshan

6
Se você está se referindo a essa forma de pré-processamento, então não, os modelos C ++ não são absolutamente algum tipo de macro glorificada.
precisa saber é o seguinte

1
A linguagem do modelo está realmente completa, por isso são muito mais do que macros aprimoradas.
Davidk01

Respostas:


9

Modelos C ++ são uma espécie de macros Lisp (ou mais ainda, Scheme). É uma linguagem completa de Turing que avalia em tempo de compilação, mas é severamente limitada, pois não há acesso dessa linguagem ao ambiente C ++ subjacente. Portanto, sim, os modelos C ++ podem ser vistos como alguma forma de pré-processamento, com uma interação muito limitada com o código sendo gerado.


2
"mas é severamente limitado, pois não há acesso dessa linguagem ao ambiente C ++ subjacente." -- O que isso significa? Tentei analisar esta afirmação, mas falhei.
quant_dev


3
@ SK-logic: Além disso, o C ++ 11 é C ++, a menos que você (pedanticamente) trate versões diferentes do mesmo idioma que idiomas diferentes.
Jon Purdy

3
@ Jon Purdy, o C ++ 11 não existia (oficialmente) no momento desta resposta. Atualmente, um exemplo seria mais complicado, como decompor uma estrutura de dados, usar uma função de biblioteca etc.
SK-logic

1
@ SK-logic: Você conhece a implementação de C ++ com macros do tipo Lisp? Estou ficando cansado das limitações do modelo. Um exemplo da linguagem de sintaxe no estilo C ++ com o poderoso sistema de macros no Haxe: haxe.org/manual/macros . (Não me ajuda porque uso C ++ para esse fim - programação de microcontroladores de 8 bits; existem linguagens melhores para qualquer outra coisa).
Pfalcon #

41

Provavelmente, a maior diferença é que as macros C são expandidas na fase de pré-processamento, antes de qualquer outra compilação, enquanto os modelos C ++ fazem parte da compilação. Isso significa que os modelos C ++ têm reconhecimento de tipo e escopo, entre outras coisas, e não são uma simples substituição de texto. Eles podem ser compilados para funções reais e, portanto, evitar a maioria dos problemas que as macros têm. Estar ciente do tipo significa que eles podem ser gerais ou especializados: por exemplo, é fácil fornecer uma swapfunção de modelo e escrever especializações que funcionam bem, mesmo que os objetos gerenciem a memória heap.

Portanto, os modelos C ++ não estão pré-processando no mesmo sentido que as macros, não são um tipo de macro C e é impossível usar macros C para duplicar o que os modelos fazem.

Os modelos vivem em arquivos de cabeçalho, não em bibliotecas vinculadas, é verdade, mas se você estiver fornecendo uma .dll, provavelmente também estará fornecendo um arquivo de cabeçalho para uso.


12
Eles não precisam viver no arquivo de cabeçalho (essa é apenas a técnica mais simples de usá-los). Você pode defini-los em um arquivo de origem e forçar manualmente a instanciação do modelo no arquivo de origem (unidade de compilação). O link selecionará as instanciações normalmente (essa é uma técnica para limitar modelos a tipos específicos e não permitir todos os tipos genéricos).
Martin York

@ Martin: Não tenho certeza se esta técnica (enquanto suportada) é realmente explicitamente suportada pelo padrão. Caso contrário, todos os compiladores já teriam exportimplementado. Sei que funciona para funções, mas duvido que funcione para as aulas: como você saberia o tamanho delas?
Matthieu M.

@ Matthieu M: Isso não tem nada a ver com a palavra-chave de exportação. Ele lida com a instanciação explícita do modelo e está bem definido no padrão.
Martin York

2
@ Matthieu M .: Se o compilador conhece a assinatura de uma função e o vinculador pode encontrar uma implementação, tudo é legal. Isso se aplica se a função é ou não uma função de modelo. Na prática, eles geralmente vivem em arquivos de cabeçalho, porque forçar instanciações específicas geralmente é mais trabalhoso do que vale a pena, mas Martin está correto ao observar a alternativa.
precisa

Eu sei que funciona, com certeza, para funções especializadas. No entanto, também tenho certeza de que não funciona para as aulas, o que foi o meu ponto. Eu acho que funciona para métodos de classes especializadas também, mas não sei se isso é padrão ou não.
Matthieu M.

5

Importa como eles são implementados? Os primeiros compiladores C ++ eram apenas pré-processadores que alimentavam o código para o compilador CA, não significa que C ++ seja apenas uma macro glorificada.

Os modelos eliminam a necessidade de macros, fornecendo uma maneira mais segura, eficiente e especializada (mesmo que eu não ache que seja uma palavra real) de implementar código para vários tipos.

Existem várias maneiras de criar modelos de código de tipo em c, nenhum dos quais é muito bom quando você vai além dos tipos simples.


Eu não disse sobre C ++ ser uma macro glorificada. Eu admiro muito o C ++. Apenas sendo curioso.
Gulshan

2
@Gulshan: Não, você não disse nada sobre isso. No entanto, foi assim que os primeiros compiladores C ++ funcionaram (exceto que o CFront era um compilador em vez de apenas um pré-processador de macro), e suas declarações sobre modelos C ++ são aplicáveis ​​ao próprio C ++ inicial.
David Thornley

O CFront compilou C ++ a C. A linha entre pré-processador e compilador é claramente definida: um compilador tenta entender sua entrada - por meio de análise, criação de AST, etc. - enquanto um pré-processador não - por exemplo, usando apenas substituição textual ou de token.
Jon Purdy

1
Acho que o que David quis dizer é que existe um subconjunto subjacente de C ++ e que os modelos podem ser considerados como algum tipo de macros que são usadas para generalizar um programa nesse subconjunto, que pode ser compilado como um estágio adicional e separado.
Giorgio

5

Existem algumas diferenças; por exemplo, os modelos podem ser usados ​​para instanciar uma sobrecarga de função quando necessário; enquanto nas macros, você precisa expandir a macro uma vez para cada sobrecarga possível, a fim de torná-la visível ao compilador, para acabar com muitas de código não utilizado.

Outra diferença é que os modelos respeitam os espaços para nome.


2

IMHO, modelos C ++ e macros C foram criados para resolver dois problemas completamente diferentes. A biblioteca de modelos padrão C ++ original era um mecanismo para separar de maneira limpa as classes de contêineres (matrizes, listas vinculadas etc.) das funções genéricas comumente aplicadas a elas (como classificação e concatenação). Ter representações abstratas de algoritmos e estruturas de dados eficientes leva a um código mais expressivo, porque havia significativamente menos suposições sobre a melhor forma de implementar uma função que trabalha em uma determinada peça de dados. As macros C estavam muito mais alinhadas com o que normalmente seria visto nas macros Lisp, na medida em que forneciam um meio de "estender" o idioma com código embutido. O legal é que a Biblioteca Padrão C ++ estendeu a funcionalidade dos modelos para cobrir a grande maioria do que usamos #define em C.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.