260 likes | 341 Views
Metaprogramação Estática. André Knabben Pricilla Padaratz. Metaprogramação. Envolve escrever programas relacionados pela meta-relação relação de “ser sobre” Programas que manipulam e geram outros programas. Metaprogramação Estática.
E N D
Metaprogramação Estática André Knabben Pricilla Padaratz
Metaprogramação • Envolve escrever programas relacionados pela meta-relação relação de “ser sobre” • Programas que manipulam e geram outros programas
Metaprogramação Estática • Metaprogramas estáticos são executados antes do código que eles manipulam em tempo de compilação • Compiladores e pré-processadores • Open Compiler tornar a metaprogramação mais acessível
Templates • Metaprogramação em C++ • Classes e funções que operam com números e/ou tipos como dados • Recursão de templates • Especialização de templates
Templates • Compilador executa operações codificam-se dados como tipos usa-se o compilador para interpretar metaprogramas Templates Reutilizar código fonte X Herança e Composição Reutilizar código de objetos
Classes • Implementação de templates genéricos com paramêtros de tipo • Compilador gera a classe de acordo com o tipo • Por exemplo: template<class T> class Fila { ...} Fila<int>, Fila<Clientes>, etc.
Funções • Implementação de funções genéricas que podem ser usadas com tipos arbitrários • Compilador gera código de acordo com o tipo • Rotinas de busca, rotinas de sort • Exemplo: template<class T> T max(T a, T b) { return a > b ? a : b; }
Especialização • É possível definir especializações de templates para tipos específicos • Especialização de classes e de funções • Exemplo: template<class T> class Lista { ... } template<> class Lista<char> { ... } O template Lista<char> é usado para definir Listas de caracteres; outras Listas serão geradas a partir do template base Lista<class T>
Especialização Parcial • Usada para gerar especializações de templates onde alguns parâmetros permanecem fixos e outros variam • Não são suportados por todos os compiladores • Suportado pelos GCC mais recentes • Suportado pelo compilador da Intel • Não suportado pelo Visual C++ 6.0
Exemplo • template<bool cond, class ThenType, class ElseType> struct IF { typedef ThenType RET; }; template<class ThenType, class ElseType> struct IF<false, ThenType, ElseType> { typedef ElseType RET; };
Meios de prover informação sobre tipos • Definir um traits template para o tipo: Traits templates provêem informações sobre outros tipos • Colocar a informação diretamente como parte do tipo (member traits) • Criar uma classe com os traits (trait classes)
Promoção de tipos • Traits podem ser usados para promover tipos • X = Y + Z: resultado da operação + assume tipo de acordo com algum critério (int + double => double) • Exemplo de uso: classes matemáticas
Princípios de Codificação • Typedef: atribuição para tipo • Enum: atribuição para valor • Recursão de template: loop • Operador ? : e especialização de template: condicional • Uso de namespace e private/protected para ocultar operações intermediárias
Instantiation/Lazyness • Compilador instancia templates apenas quando necessário • Ex: • template <class T> struct X { /*code */} • typedef X<int> X_INT; // não • X_INT *x; // não • X_INT x; // sim
Instantiation/Lazyness template <class T_> class Uma{ typedef T_ Tipo;}; template <class T_> class Outra{ typedef T_ Tipo; }; typedef IF<cond, Uma<int>::Tipo, Outra<bool>::Tipo>::RET TIPO1; // ruim typedef IF<cond, Uma<int>, Outra<bool> >::RET::Tipo TIPO1; // bom template class vector<int>; // instanciação explícita
Outros templates como parâmetro template <class T> struct Base { /* code */ } template < class ElementType, template<class>class ListType > struct ListUser { typedef ListType<Proxy<ElementType> > MyList; };
Alternativa: Criar estrutura para passar um parâmetro template struct UsarTipo1{ template <class Internal> struct UseType{ typedef Tipo1<Internal> RET; };}; template <class ListTypeTemplate> struct ListUser{ typedef TipoTemplate::UseType<Proxy<int> >::RET MyList;};
Expression Templates • Servem para otimizar/restringir o uso de expressões usando redefinição de operadores • M1 = (M2 + M3 + M4) * M5; • Permite: • Armazenar as operações a serem executadas e otimizar a expressão (incluindo as mesmas otimizações que o compilador faria); • Adicionar restrições adicionais do domínio tratado.
Exemplo: Expression Templates • (4 * 3) + 10
Compilando com o G++ • In file included from lista.h:6, • from lista.cpp:1: • smp_inherit.h:39: parse error before `;' token • template <class ChildType> • struct UseType • { • typedef typename Type<ChildType> RET; • };
Problemas • Ferramentas/compiladores não estão preparadas para o uso intensivo de templates • Não há como verificar como o compilador está instanciando os templates • Problemas com o debug • Mensagens de erro ruins • Recursos de autocompletar não funcionam
Ex. Mensagem do compilador Z:\SMP\teste\src\main.cpp(66): error: no suitable constructor exists to convert from "LinkedNode<GenerateSubClass<int, LinkedNode, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTypeList>>>>::NodeType *" to "DoublyLinkedNode<GenerateSubCla ssInternals::GenerateSubClass_<GenerateSubClassInternals::GenerateSubClass_<GenerateSubClass<int, LinkedNode, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTypeList>>>::Env={int}, LinkedNode<GenerateSubClass<int, LinkedNode, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTypeList>>>>, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTypeList>>>::Env={GenerateSubClass<int, LinkedNode, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTy peList>>>::Env={int}}, LinkedNode<GenerateSubClass<int, LinkedNode, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTypeList>>>>, SubTypeList<DoublyLinkedNode, SubTypeList<LengthNode, EndTypeList>>::Tail>::RET>" *last = (x.next)->next->next;
Bibliografia • CZARNECKI, K., EISENECKER, U. Generative Programming: Methods, Techniques and Applications. Addison-Wesley, 2000. • C++ Templates Tutorial: http://babbage.cs.qc.edu/STL_Docs/templates.htm