modelos em C++editar

artigo principal: Modelo (C++)

C++ usa modelos para permitir técnicas de programação genéricas. A Biblioteca Padrão C++ inclui a Biblioteca Padrão de Template ou STL que fornece uma estrutura de modelos para estruturas de dados e algoritmos comuns. Templates in C++ may also be used for template metaprogramming, which is a way of pre-evaluating some of the code at compile-time rather than run-time. Usando especialização de modelos, modelos C++ são considerados Turing completos.,

overviewEdit técnico

Existem dois tipos de modelos: modelos de função e modelos de classe. Um modelo de função é um padrão para criar funções ordinárias baseadas nos tipos parametrizantes fornecidos quando instanciados. Por exemplo, a biblioteca de modelos padrão C++ contém o modelo de função max(x, y) que cria funções que retornam x ou y, o que for maior., max() poderia ser definido assim:

template <typename T>T max(T x, T y) { return x < y ? y : x;}

Especializações deste modelo de função, instanciações com tipos específicos, podem ser chamados assim como uma função comum:

std::cout << max(3, 7); // Outputs 7.

O compilador analisa os argumentos usados para chamar max e determina que esta é uma chamada para max(int, int)., Em seguida, ele cria uma versão da função onde a parametrização T tipo é int, tornando o equivalente a função a seguir:

int max(int x, int y) { return x < y ? y : x;}

Isto funciona se os argumentos x e y são números inteiros, cadeias de caracteres, ou qualquer outro tipo para o qual a expressão x < y é sensível, ou mais especificamente, para qualquer tipo para o qual o operador< está definido. Herança comum não é necessária para o conjunto de tipos que podem ser usados, e por isso é muito semelhante à datilografia de pato., Um programa que define um tipo de dados personalizado pode usar sobrecarga de operador para definir o Significado de < para esse tipo, permitindo assim o seu uso com o modelo de função max (). Embora isso possa parecer um benefício menor neste exemplo isolado, no contexto de uma biblioteca abrangente como o STL, ele permite ao programador obter uma funcionalidade extensiva para um novo tipo de dados, apenas definindo alguns operadores para ele., Apenas a definição de < permite que um tipo para ser usado com o padrão de classificação(), stable_sort(), e binary_search() algoritmos ou para ser colocado dentro de estruturas de dados, tais como conjuntos, pilhas, e arrays associativos.

os modelos C++ são completamente seguros no tempo de compilação. Como uma demonstração, o complexo de Tipo padrão não define o < operador, porque não há nenhuma ordem estrita em números complexos. Portanto, max (x, y) vai falhar com um erro de compilação, se x e y são valores complexos., Da mesma forma, outros modelos que dependem de < não podem ser aplicados a dados complexos a menos que seja fornecida uma comparação (na forma de um functor ou função). Por exemplo: um complexo não pode ser usado como chave para um mapa a menos que seja fornecida uma comparação. Infelizmente, os compiladores historicamente geram mensagens de erro um pouco Esotéricas, longas e inúteis para este tipo de erro. Garantir que um determinado objeto adere a um protocolo método pode aliviar esta questão. Linguagens que usam comparar em vez de < também podem usar valores complexos como chaves.,

O segundo tipo de modelo, um modelo de classe, estende o mesmo conceito para classes. A classe template specialization é uma classe. Modelos de classe são frequentemente usados para fazer recipientes genéricos. Por exemplo, o STL tem um container listado vinculado. Para fazer uma lista ligada de inteiros, escreve-se uma lista<int>. A list of strings is denoted list<string>. Uma lista tem um conjunto de funções padrão associadas a ela, que funcionam para qualquer tipo de parametrização compatível.,

Especializationedit de modelo

uma característica poderosa dos modelos de C++é a especialização de modelos. Isto permite implementações alternativas a serem fornecidas com base em certas características do tipo parametrizado que está sendo instanciado. Especialização de Template tem dois propósitos: permitir certas formas de otimização, e reduzir o inchaço de código.

por exemplo, considere uma função de modelo sort (). Uma das principais atividades que tal função faz é trocar ou trocar os valores em duas posições do recipiente., Se os valores são grandes (em termos do número de bytes que leva para armazenar cada um deles), então é muitas vezes mais rápido primeiro construir uma lista separada de ponteiros para os objetos, ordenar esses ponteiros, e, em seguida, construir a sequência ordenada final. Se os valores são bastante pequenos, no entanto, é geralmente mais rápido para apenas trocar os valores no local, conforme necessário. Além disso, se o tipo parametrizado já é de algum tipo de ponteiro, então não há necessidade de construir um conjunto de ponteiros separado., A especialização do modelo permite ao criador do modelo escrever diferentes implementações e especificar as características que o(S) Tipo (s) parametrizado (s) deve (M) ter para cada implementação a ser usada.

Ao contrário dos modelos de função, os modelos de classe podem ser parcialmente especializados. Isso significa que uma versão alternativa do Código do modelo de classe pode ser fornecida quando alguns dos parâmetros do modelo são conhecidos, deixando outros parâmetros do modelo genéricos., Isto pode ser usado, por exemplo, para criar uma implementação padrão (a especialização primária) que assume que copiar um tipo parametrizante é caro e, em seguida, criar especializações parciais para tipos que são baratos de copiar, aumentando assim a eficiência geral. Clientes de tal modelo de classe apenas usam especializações dele sem precisar saber se o compilador usou a especialização primária ou alguma especialização parcial em cada caso., Os modelos de classe também podem ser totalmente especializados, o que significa que uma implementação alternativa pode ser fornecida quando todos os tipos de parametrização são conhecidos.

vantagens e desvantagens

alguns usos de modelos, tais como a função max (), foram previamente preenchidos por macros pré-processadores de função similar (um legado da linguagem de programação C). Por exemplo, aqui está uma possível macro max ():

#define max(a,b) ((a) < (b) ? (b) : (a))

Macros são expandidas pelo pré-processador, antes da compilação propriamente dita; os modelos são expandidos no tempo de compilação., Macros são sempre expandidos em Linha; modelos também podem ser expandidos como funções em linha quando o compilador o considera apropriado. Assim, tanto macros como modelos de funções não têm sobrecarga de tempo de execução.no entanto, os modelos são geralmente considerados uma melhoria em relação às macros para estes fins. Os modelos são de tipo seguro. Modelos evitam alguns dos erros comuns encontrados no código que faz uso pesado de macros Função-Tipo, tais como avaliar parâmetros com efeitos colaterais duas vezes. Talvez mais importante, modelos foram projetados para serem aplicáveis a problemas muito maiores do que macros.,

Existem quatro desvantagens primárias para o uso de modelos: recursos suportados, Suporte de compilador, mensagens de erro pobres, e bloat de código:

  1. modelos em C++ não possuem muitas características, o que torna a sua implementação e utilização de uma forma simples muitas vezes impossível. Em vez disso, os programadores têm que confiar em truques complicados que levam a inchado, difícil de entender e difícil de manter o código. Os desenvolvimentos atuais nos padrões C++ exacerbam este problema, fazendo uso pesado destes truques e construindo um monte de novos recursos para modelos neles ou com eles em mente.,
  2. muitos compiladores historicamente têm baixo suporte para modelos, assim o uso de modelos pode tornar o código um pouco menos portátil. O suporte também pode ser pobre quando um compilador C++ está sendo usado com um linker que não está ciente de C++, ou ao tentar usar modelos através dos limites de bibliotecas compartilhadas. A maioria dos compiladores modernos, no entanto, agora têm um suporte de modelo bastante robusto e padrão, e o novo padrão C++, C++11, aborda ainda mais essas questões.
  3. quase todos os compiladores produzem mensagens de erro confusas, longas ou por vezes inúteis quando os erros são detectados em código que usa modelos., Isso pode tornar os modelos difíceis de desenvolver.
  4. finalmente, o uso de modelos requer que o compilador gere uma instância separada da classe ou função templated para cada permutação dos parâmetros de tipo usados com ele. (Isso é necessário porque os tipos em C++ não são todos do mesmo tamanho, e os tamanhos dos campos de dados são importantes para como as classes funcionam.) Assim, o uso indiscriminado de modelos pode levar ao inchaço do Código, resultando em executáveis excessivamente grandes., No entanto, o uso criterioso da especialização e derivação de modelos pode reduzir drasticamente tal inchaço de código em alguns casos:

assim, pode derivação ser usada para reduzir o problema de código replicado porque modelos são usados? Isso envolveria derivar um modelo de uma classe comum. Esta técnica provou ser bem sucedida na contenção do inchaço do código em uso real. Pessoas que não usam uma técnica como esta descobriram que o código replicado pode custar megabytes de espaço de código mesmo em programas de tamanho moderado.,

— Bjarne Stroustrup, a Concepção e A Evolução de C++, 1994

O extra instâncias geradas por modelos também podem causar depuradores ter dificuldades para trabalhar correctamente com modelos. Por exemplo, definir um ponto de paragem de depuração dentro de um modelo de um ficheiro de código pode falhar a definição do ponto de paragem na instanciação actual desejada ou pode definir um ponto de paragem em todos os locais em que o modelo está instanciado.,

também, porque o compilador precisa executar expansões macro-like de modelos e gerar diferentes instâncias deles no tempo de compilação, o código fonte de implementação para a classe ou função templated deve estar disponível (por exemplo, incluído em um cabeçalho) para o código usando-o. Classes ou funções templadas, incluindo grande parte da Biblioteca Padrão de modelos (STL), se não estiver incluída em arquivos de cabeçalho, não podem ser compiladas. (This is in contrast to non-templated code, which may be compiled to binary, providing only a declarations header file for code using it.,) Isto pode ser uma desvantagem ao expor o código de implementação, que remove algumas abstrações, e poderia restringir seu uso em projetos de código fechado.

modelos no DEdit

a linguagem de programação D suporta modelos baseados no design em C++.,Mais C++ modelo de expressões idiomáticas será levada para D sem alteração, mas D adiciona algumas funcionalidades adicionais:

  • Modelo de parâmetros em D não está restrito a apenas tipos e valores primitivos, mas também permitir arbitrários de tempo de compilação valores (tais como cadeias de caracteres e estrutura literais), e aliases para arbitrário identificadores, incluindo outros modelos ou instanciações de modelo.
  • Template constraints and the static if statement provide an alternative to C++ ‘ s substitution failure is not an error (SFINAE) mechanism, similar to C++ concepts.
  • O is(…,) expression allows speculative instantiation to verify an object’s traits at compile time.
  • A Palavra-chave automática e o tipo de expressão permitem inferência de tipo para declarações variáveis e valores de retorno de função, que por sua vez permite “tipos Voldemort” (tipos que não têm um nome global).

Modelos em D usar uma sintaxe diferente do que em C++: considerando que, em C++ parâmetros do modelo são envolto em colchetes angulares (Modelo<param1, param2>),D usa um sinal de exclamação e entre parênteses: Modelo!(param1, param2).,Isso evita as dificuldades de processamento Em C++ devido à ambiguidade com os operadores de comparação.Se houver apenas um parâmetro, os parênteses podem ser omitidos.

convencionalmente, D combina as características acima para fornecer polimorfismo de tempo de compilação usando programação genérica baseada em traços.,Por exemplo, um intervalo de entrada é definida como qualquer tipo que satisfaça as verificações efectuadas por isInputRange, que é definido da seguinte forma:

Uma função que aceita apenas faixas de entrada, em seguida, pode utilizar o modelo acima em um modelo de restrição:

auto fun(Range)(Range range) if (isInputRange!Range){ // ...}
Código generationEdit

além de template metaprogramming, D também fornece vários recursos para permitir tempo de compilação e geração de código:

  • A importação de expressão que permite a leitura de um ficheiro a partir do disco e utilização de seu conteúdo como uma expressão de seqüência de caracteres.,a reflexão em tempo de compilação permite enumerar e inspeccionar as declarações e os seus membros durante a compilação.
  • atributos definidos pelo utilizador permitem aos utilizadores anexar identificadores arbitrários às declarações, que podem então ser enumerados utilizando uma reflexão de tempo de compilação.
  • execução da função de tempo de Compilação (CTFE) permite que um subconjunto de D (restrito a operações seguras) seja interpretado durante a compilação.
  • String mixins permite avaliar e compilar o conteúdo de uma expressão de string como código D que se torna parte do programa.,

combinando o acima permite gerar código com base em declarações existentes.Por exemplo, os frameworks de serialização D podem enumerar os membros de um tipo e gerar funções especializadas para cada tipo serializado para executar serialização e deserialização.Atributos definidos pelo Usuário poderiam ainda indicar regras de serialização.

a expressão de importação e a execução da função compile-time também permitem a implementação eficiente de linguagens específicas ao Domínio.,Por exemplo, dada uma função que toma uma cadeia que contém um modelo HTML e devolve código fonte d equivalente, é possível usá-la da seguinte forma:

Genericidade em classes genéricas eiffeledit

fazem parte do Eiffel desde o método original e desenho da linguagem. As publicações da Fundação Eiffel, usam o termo genericidade para descrever a criação e uso de classes genéricas.as classes genéricas

Basic/Unconstrainedit

são declaradas com o seu nome de classe e uma lista de um ou mais parâmetros genéricos formais., No código a seguir, a classe LIST tem um formais parâmetro genérico G

O formal de parâmetros genéricos são marcadores de posição para arbitrário nomes de classe que será fornecido quando uma declaração da classe genérica é feito, como é mostrado nas duas genérico derivações abaixo, onde ACCOUNT e DEPOSIT são outros nomes de classe. ACCOUNTeDEPOSITsão considerados parâmetros genéricos reais uma vez que fornecem nomes de classe reais para substituirG no uso real.,

 list_of_accounts: LIST -- Account list list_of_deposits: LIST -- Deposit list

no sistema do tipo Eiffel, embora a classe LIST seja considerada uma classe, não é considerada um tipo. No entanto, uma derivação genérica de LIST tal comoLIST é considerado um tipo.

Genericityedit

para a classe da lista mostrada acima, um parâmetro genérico real substituindo por G pode ser qualquer outra classe disponível., Para restringir o conjunto de classes a partir das quais os parâmetros genéricos reais válidos podem ser escolhidos, uma restrição genérica pode ser especificada. Na declaração da classe SORTED_LIST abaixo, a restrição genérica determina que qualquer validade real do parâmetro genérico vai ser uma classe que herda da classe COMPARABLE. A restrição genérica garante que elementos de um SORTED_LIST podem de fato ser ordenados.,

class SORTED_LIST 

Generics in JavaEdit

Main article: Generics in Java

Support for the generics, or” containers-of-type-T ” was added to the Java programming language in 2004 as part of J2SE 5.0. Em Java, OS genéricos só são verificados na hora de compilação para a correção do tipo. A informação de tipo genérico é então removida através de um processo chamado de apagamento de tipo, para manter a compatibilidade com as implementações JVM antigas, tornando-o indisponível em tempo de execução., Por exemplo, uma lista<String> é convertida para a lista de tipos brutos. O compilador insere tipos de moldes para converter os elementos para o tipo de cadeia quando eles são recuperados da lista, reduzindo o desempenho em comparação com outras implementações, como modelos c++.

Genericity in. net Edit

Generics were added as part of. NET Framework 2.0 in November 2005, based on a research prototype from Microsoft Research started in 1999. Embora semelhante aos genéricos em Java, .,Os genéricos do NET não aplicam apagamento de tipo, mas implementam genéricos como um mecanismo de primeira classe no tempo de execução usando reificação. Esta escolha de projeto oferece funcionalidade adicional, como permitir reflexão com a preservação de tipos genéricos, bem como aliviar algumas das limitações do apagamento (como ser incapaz de criar arrays genéricos). Isto também significa que não há nenhum desempenho atingido a partir de moldes de runtime e conversões de boxe normalmente caro., Quando tipos primitivos e de valor são usados como argumentos genéricos, eles recebem implementações especializadas, permitindo coleções e métodos genéricos eficientes. Como em C++ e Java, tipos genéricos aninhados, como Dicionário<string, Lista<int>> são válidos tipos, no entanto, são desaconselhadas para o membro de assinaturas na análise de código de regras de estrutura.

.,NET permite que seis variedades de restrições de tipo genérico usando a palavra-chave onde, incluindo a restrição de tipos genéricos para ser tipos de valor, para ser classes, para ter construtores, e para implementar interfaces. Abaixo está um exemplo com uma restrição de interface:

O MakeAtLeast() método permite a operação em arrays com elementos do tipo genérico T. O tipo do método de restrição indica que o método é aplicável para qualquer tipo T, que implementa o genérico IComparable<T> interface., Isto garante um erro de tempo de compilação, se o método for chamado se o tipo não suportar a comparação. A interface fornece o método genérico de CompareTo (T).

o método acima também pode ser escrito sem tipos genéricos, simplesmente usando o tipo de Array não-Genérico. No entanto, uma vez que arrays são contraditórios, a fundição não seria segura do tipo, e o compilador seria incapaz de encontrar certos erros possíveis que de outra forma seriam capturados ao usar tipos genéricos. Além disso, o método precisaria acessar os itens array como objetos em vez disso, e exigiria a fundição para comparar dois elementos., (Para tipos de valor, como tipos como int, esta requer uma luta de boxe de conversão, embora isso pode ser contornado usando o Comparador<T> classe, como é feito no padrão de coleta de classes.)

a notable behavior of static members in a generic. net class is static member instantiation per run-time type (see example below).

Genericity in DelphiEdit

Delphi’s Object Pascal dialect acquired generics in the Delphi 2007 release, initially only with the (now discontinued) .,NET compiler before being added to the native code in the Delphi 2009 release. A semântica e as capacidades do Delphi generics são em grande parte modeladas com base nas que o generics tinha no.NET 2.0, embora a implementação seja necessariamente muito diferente. Aqui está uma tradução mais ou menos direta do primeiro exemplo C# mostrado acima:

Como com C#, métodos, bem como tipos inteiros podem ter um ou mais parâmetros de tipo. No exemplo, TArray é um tipo genérico (definido pela linguagem) e MakeAtLeast um método genérico., The available constraints are very similar to the available constraints in C#: any value type, any class, a specific class or interface, and a class with a parameterless constructor. Múltiplas restrições agem como uma união aditiva.

Genericity in Free PascalEdit

Free Pascal implemented generics before Delphi, and with different syntax and semantics. No entanto, desde a versão 2.6.0 do FPC,a sintaxe do estilo Delphi está disponível ao usar o modo {$mode Delphi} linguagem. Assim, programadores Free Pascal são capazes de usar genéricos em qualquer estilo que eles preferem.,

Delphi and Free Pascal example:

Functional languagesEdit

Genericity in HaskellEdit

the type class mechanism of Haskell supports generic programming.Seis das classes de tipo predefinidas em Haskell (incluindo Eq, os tipos que podem ser comparados para a igualdade, e mostrar, os tipos cujos valores podem ser renderizados como cadeias) têm a propriedade especial de suportar instâncias derivadas., Isto significa que um programador definindo um novo tipo pode afirmar que este tipo deve ser uma instância de uma dessas classes de tipo especial, sem fornecer implementações dos métodos de classe como normalmente é necessário ao declarar instâncias de classe. Todos os métodos necessários serão “derivados” – ou seja, construídos automaticamente-baseados na estrutura do tipo.,Por exemplo, a seguinte declaração de um tipo de árvores binárias afirma que é ser uma instância das classes Eq e Mostrar:

data BinTree a = Leaf a | Node (BinTree a) a (BinTree a) deriving (Eq, Show)

Isto resulta em uma igualdade função (==) e uma representação de seqüência de caracteres de função (mostrar) a ser definido automaticamente para qualquer tipo de formulário BinTree T desde que o próprio T oferece suporte a essas operações.,

O suporte para derivadas de instâncias de Eq e Mostrar faz com que seus métodos == e mostrar genérico de forma qualitativamente diferente de para-metrically polimórficos funções: essas “funções” (mais precisamente, tipo indexado de famílias de funções) podem ser aplicados a valores de vários tipos, e embora eles se comportam de maneira diferente para cada tipo de argumento, pouco é necessário mais trabalho para adicionar suporte para um novo tipo. Ralf Hinze (2004) mostrou que um efeito semelhante pode ser alcançado para classes de tipo definidas pelo usuário por certas técnicas de programação., Outros pesquisadores têm proposto abordagens para este e outros tipos de genericidade no contexto de Haskell e extensões para Haskell (discutido abaixo).

PolyPEdit

PolyP foi a primeira extensão genérica de linguagem de programação para Haskell. Em polip, funções genéricas são chamadas de politípicas. A linguagem introduz uma construção especial na qual tais funções polytípicas podem ser definidas através de indução estrutural sobre a estrutura do functor padrão de um datatype regular. Os tipos de dados regulares em PolyP são um subconjunto de tipos de dados Haskell., Um datatype regular T deve ser do tipo*→*, e se a é o argumento do tipo formal na definição, então todas as chamadas recursivas para t devem ter o formulário t A. estas restrições descartam tipos de dados mais altos, bem como tipos de dados aninhados, onde as chamadas recursivas são de uma forma diferente.A função flatten em PolyP é aqui fornecida como um exemplo:

HaskellEdit Genérico

Haskell Genérico é outra extensão para Haskell, desenvolvida na Universidade de Utrecht, nos Países Baixos., As extensões que ele fornece São:

  • valores indexados de tipo são definidos como um valor indexado sobre os vários construtores de tipo Haskell (unidades, tipos primitivos, somas, produtos e construtores de tipo definidos pelo Usuário). Além disso, também podemos especificar o comportamento de um tipo de valores indexados para um construtor específico usando casos de construtores, e reutilizar uma definição genérica em outro usando casos padrão.

o valor indexado tipo resultante pode ser especializado em qualquer tipo.

  • Tipos indexados ao tipo são tipos indexados sobre tipos, definidos dando um caso para ambos * e k → k’., Instâncias são obtidas aplicando o tipo indexado a um tipo.
  • definições genéricas podem ser usadas aplicando-as a um tipo ou tipo. Isto é chamado de aplicação genérica. O resultado é um tipo ou valor, dependendo de que tipo de definição genérica é aplicada.
  • abstração Genérica permite que Definições genéricas sejam definidas abstraindo um parâmetro de tipo (de um determinado tipo).
  • Tipos indexados por tipo são tipos que são indexados sobre os construtores de tipo. Estes podem ser usados para dar tipos a valores genéricos mais envolvidos., Os tipos indexados de tipo resultantes podem ser especializados a qualquer tipo.

Como exemplo, a função de igualdade em Haskell Genérico:

CleanEdit

Clean oferece PolyP Genérico baseado na programação e o Haskell genérico como suportado pelo GHC>=6.0. Parametrizes by kind as those but offers overloading.

outras languagesEdit

a família ML de linguagens de programação suporta programação genérica através de polimorfismo paramétrico e módulos genéricos chamados functors.,Tanto o padrão ML quanto o OCaml fornecem functores, que são similares aos modelos de classe e aos pacotes genéricos de Ada. Scheme syntactic abstractions also have a connection to genericity-these are in fact a superset of templating à la c++.

um módulo Verilog pode tomar um ou mais parâmetros, aos quais os seus valores reais são atribuídos na instanciação do módulo. Um exemplo é um conjunto genérico de registradores onde a largura do array é dada através de um parâmetro., Tal array, combinado com um vetor de fio genérico, pode fazer um buffer genérico ou módulo de memória com uma largura de bits arbitrária de uma única implementação de Módulo.

VHDL, sendo derivado de Ada, também tem capacidades genéricas.