Existem recursos para identificar problemas que poderiam ser melhor resolvidos com modelos?

8

Decidi melhorar meus conhecimentos em meta-programação de modelos. Conheço a sintaxe e as regras e tenho jogado com inúmeros exemplos de recursos online.

Entendo o quanto os modelos podem ser poderosos e a otimização do tempo de compilação que eles podem fornecer, mas ainda não consigo "pensar em modelos", não consigo saber por mim mesmo se um determinado problema pode ser melhor resolvido com modelos e, se puder, como adaptar esse problema aos modelos.

Existe algum tipo de recurso ou livro on-line que ensina como identificar problemas que poderiam ser melhor resolvidos com modelos e como adaptar esse problema?

seiva
fonte
5
Se tudo o que você tem é um martelo, tudo parece um prego ;-) Não tente pensar demais em usar modelos para tudo e tudo, pelo menos, não se você não quiser criar a próxima versão do padrão C ++ biblioteca.
Doc Brown
você está certo, não vou olhar para o código de produção e tentar ajustar o TMP em qualquer lugar heh: p isso é apenas para aprendizado pessoal, porque eu sei o quão poderosos eles podem ser e eu amo como alguns grandes programadores de C ++ (como o STL que trabalha no MS) pode aplicar o TMP tão rápido a um determinado problema e isso parece tão impressionante. A STL tem alguns vídeos no canal9 que realmente me impressionaram com o TMP e é por isso que quero saber mais.
sap

Respostas:

8

Livros:

Design moderno em C ++

Metaprogramação de modelos C ++

Estar familiarizado com a recursão e a programação funcional é uma enorme vantagem, pois é isso que envolve muito tmp. Ele está completo e, portanto, essencialmente tudo é possível, embora geralmente tudo se refira a aplicar funções puras a constantes ou a gerar tipos de outros tipos.

Atenção: tmp é um monstro feio que transforma um bom código em espaguete. Quanto mais você usa, menos você gosta de C ++. É uma coisa má.

Pubby
fonte
1
+1 para "tmp é um monstro feio". C ++ é bom em algumas coisas, como em qualquer linguagem; mas a metaprogramação não é uma delas.
Jon Purdy
"Design moderno em C ++" é um clássico, mas o IIRC é mais sobre implementar coisas usando truques inteligentes de modelos do que sobre decidir o que deve ser implementado como modelo. O não. Um princípio para isso é provavelmente "não" - os motivos mais comuns para a necessidade de um modelo já estão cobertos pela biblioteca padrão (especialmente C ++ 11), Boost e outras bibliotecas já existentes, portanto, é necessário rolar suas próprio não é realmente uma coisa cotidiana.
Steve314
A metaprogramação de modelos C ++ é apenas o manual do usuário de uma parte do impulso. Não ensina muito sobre a escolha de aplicativos para os quais é pertinente nem sobre como fazer coisas semelhantes em C ++.
precisa saber é o seguinte
6

Aprenda Haskell ou alguma outra linguagem funcional pura (Lisp, Scheme, OCaml, para citar algumas, você pode encontrar mais na Wikipedia ).

Considerando Haskell, você pode encontrar mais informações sobre suas instalações de metaprogramação aqui .

A programação de modelos segue as mesmas regras, na verdade.

Macke
fonte
1
Observe que o Haskell possui seu próprio sistema de modelos: Modelo Haskell.
2
@MattFenwick: Sim. E ainda é Haskell, ao contrário dos modelos c ++. :)
Macke 28/11
Eu não tenho trabalhado com uma linguagem funcional desde o esquema na faculdade. Não que eu não gosto, é apenas nunca teve uma chance no trabalho e se eu tenho que gastar meu tempo livre codificação ou aprender mais eu só vez aprender algo mais :) (como TMP!)
SAP
@sap: Bem, você precisa entrar no mesmo modo de pensar ...
Macke
@sap: Na verdade, o Scheme pode ser uma ótima linguagem para se acostumar à metaprogramação em tempo de compilação. Seu sistema macro é extremamente capaz e elegante, ao mesmo tempo em que obtém um efeito semelhante aos modelos do C ++ (acho. Ainda não usei muito o C ++).
Tikhon Jelvis
2

Só porque você pode fazer algo com modelos não significa que você deveria. Praticamente falando, a menos que, quando você estiver projetando, pense que este é um trabalho incrível para modelos, provavelmente é melhor não usá-los. se você pensa demais em modelos, apenas cria um código insanamente abstrato que é tão ruim quanto uma única função gigante.

Ryathal
fonte
Obrigado pela resposta, sim, eu entendo isso, eu só quero aprender :)
sap
Eu concordo com o acima. Nos casos em que usei modelos, geralmente era o resultado da refatoração do código existente. Depois de usar o código original de novas maneiras, o modelo aparece mais claramente como uma melhoria no original. É mais difícil saber se um modelo é útil ao executar o design antes de ter casos de uso conhecidos.
Sam Goldberg
2

Lembre-se de que os modelos sendo a melhor solução são muito raros. Eu só defini o meu uma vez nos últimos 5 anos, e meus colegas que revisaram esse código nunca o fizeram. Os casos em que os modelos fazem muito sentido já foram implementados na maioria das bibliotecas padrão.

Para programação genérica, o importante a ser observado é que você está copiando e colando funções para fazer apenas pequenas alterações, como constantes ou tipos, e não consegue descobrir uma maneira limpa de usar algo como herança ou parâmetros de função para evitar repetições. você mesmo.

Uma maneira bastante comum de os modelos serem utilizados é a segurança de tipos, se você tiver tipos que se comportam da mesma forma, mas, por qualquer motivo, não os queira misturar acidentalmente.

Para o cálculo do tempo de compilação usando modelos, o importante a ser observado é o uso intensivo de recursos, onde todas as suas entradas são conhecidas em tempo de compilação, mas onde diferentes entradas constantes são usadas em diferentes locais do código. No entanto, lembre-se de que isso reduzirá a velocidade de suas compilações todas as vezes; portanto, é preferível codificar manualmente os resultados manualmente, se eles não forem alterados com muita frequência.

Alguns advogados usam modelos para micro-otimizações, como evitar pesquisas de tabelas virtuais usando polimorfismo estático ou desenrolar o loop, mas na minha opinião a complexidade geralmente supera os ganhos de desempenho, a menos que seu código seja muito crítico para o desempenho.

Karl Bielefeldt
fonte
muito obrigado pela resposta, vou manter esses pontos em mente. Eu sei que não posso usá-lo para tudo (como alguém disse antes, não posso começar a ver tudo como uma "unha") e se eu entendi corretamente o TMP é excelente no desenvolvimento de bibliotecas (C ++ inteiro), estou fazendo isso apenas para aprender e NÃO para aplicá-lo em todos os códigos de produção criados a partir de agora. e uau apenas uma vez em 5 anos? Eu acho que isso mostra como o TMP raro pode REALMENTE melhorar o código.
sap
2

Basicamente, existem vários bons motivos para usar modelos:

  1. Você tem uma função ou uma classe que possui a mesma funcionalidade para tipos diferentes. Um bom exemplo de uso de bons modelos é a biblioteca de impulso
  2. você deseja usar o polimorfismo estático e obter erros de compilação, em vez de erros em tempo de execução
  3. você deseja obter um comportamento específico, dependendo de alguns parâmetros estáticos. Por exemplo, boost :: type_traits fornece bons exemplos.
BЈовић
fonte
obrigado! Você já usou traços de tipo antes, coisas bem legais! enable_if também é uma característica do tipo? ou apenas uma "condição" da SFINAE? porque eu o usei antes (na revisão de código) e parecia tão poderoso, mas falhei em aplicá-lo a diferentes problemas.
sap
@sap É uma característica de tipo, que pode ser implementada usando SFINAE.
BЈовић
1

Você definitivamente deve procurar modelos em C ++! Isso o ajudará bastante a entender tópicos como Design Patterns e Generic Programming. Compare-os com o que outros idiomas lhe oferecem. Em detalhes, você deve usar modelos, especialmente nos seguintes cenários:

  1. Generalização e Reutilização de Código
  2. Flexibilidade
  3. Restrições de tempo e orçamento
  4. Falta de conhecimento para uma determinada tarefa

Aqui está um bom recurso on-line para você: http://en.wikipedia.org/wiki/Generic_programming#Templates_in_C.2B.2B

Maxood
fonte
eu sei o que eles podem ser usados para não apenas como aplicar esse conhecimento para determinados problemas, mas ainda um bom ler graças :)
sap
1

Um indicador simples de quando um modelo melhoraria seu código é quando você vê que seu código frequentemente exige que você projete um objeto em um tipo diferente. Um exemplo que encontrei no meu próprio código Java, o que me levou a converter uma assinatura de método existente em um modelo:

    public MsgBase getLastSentMessage(Class<? extends MsgBase> msgBaseClass)

Meu código de cliente sempre se parecia com isso:

    OrderResponse response = (OrderResponse) getLastSentMessage(OrderResponse.class);

e sempre que usei esse método, tive que converter o resultado na subclasse correta do tipo MsgBase. A assinatura do método aprimorado foi:

    public <T extends MsgBase> T getLastSentMessage(Class<T> clazz)

Agora o código do cliente era:

     OrderResponse response = getLastSentMessage(OrderResponse.class);

Então, para resumir, se você se deparar com muitas interpretações que parecem desnecessárias, você pode ter um bom caso em que um modelo limpará seu código.

Atualização: uma maneira melhor de generalizar a declaração acima:

Quando sua classe de origem será usada por objetos de muitos tipos diferentes, e a classe de origem puder interagir com esses tipos em um nível mais alto (mais abstrato), mas suas classes de clientes quiserem interagir com subtipos específicos, esse é o caso do uso de modelos . (Classes Container / List sendo o exemplo bem conhecido).

Sam Goldberg
fonte
isso é muito interessante e nunca pensei em aplicar o TMP assim, apenas mostra que realmente preciso aprender melhor e praticar mais.
sap
Ainda estou tentando descobrir os votos negativos aqui. Respondi a pergunta diretamente e forneci um exemplo concreto de quando um modelo surge de uma refatoração. Então o que estava errado?
Sam Goldberg
0

Ainda hoje, usei modelos para implementar uma máquina de estados finitos para extrair alguma contribuição. Os modelos de expressão são ferramentas extremamente poderosas para implementar conceitos de código como esse - eles funcionam como C ++ otimizado à mão e são obscenamente rápidos, mas muito genéricos e fáceis de escrever.

De um modo geral, os modelos fazem mais sentido ao implementar algoritmos genéricos. Se você não está implementando um algoritmo genérico, eles não fazem muito sentido.

DeadMG
fonte
0

Os usos mais comuns dos modelos são os seguintes:

std::vector<int> vec;
std::map<int, float> mymap;

O próximo exemplo comum é:

template<class T>
class MyArray {
public:
   virtual T get(int i) const=0;
};

Juntamente com este tipo de uso:

class ArrayImpl : public MyArray<float> {
public:
     float get(int i) const { }
};

Aquele mostrou parte importante dos modelos, que é a substituição do tipo - T é substituído pelo tipo float nos dois locais em que é usado.

tp1
fonte