Todo o uso de modelos é na metaprogramação em C ++?

8

Estou tentando entender o que é metaprogramação geral e o que é em C ++ em particular. Se eu procurar a metaprogramação em c ++, recebo tutoriais de metaprogramação de modelo (TMP), mas não há explicação para se ela apenas categoriza um uso específico de modelos ou todos os usos de modelos.

Minha pergunta é se todos os usos de modelos em C ++ são categorizados como metaprogramação. Uma explicação de por que é ou não é também seria útil. Obrigado.

joaerl
fonte
1
Compare com as macros CL e veja a décima regra de Greenspun. br.wikipedia.org/wiki/Greenspun%27s_tenth_rule
inicio
1
O TMP não é o único caminho para a metaprogramação. Pode-se também fazer metaprogramação com macros (uhh) e funções constexpr . O Constexpr pode ser mais fácil de implementar do que o TMP.
zett42 5/01
1
@ zett42 Não tenho certeza se apenas executar código em tempo de compilação é o que deve ser considerado "metaprogramação". Porque isso não é programação , mas computação. É apenas mudar a execução do tempo de execução para o tempo de compilação. A metaprogramação em C ++ é diferente disso, porque gera código (modelos, macros).
Johannes Schaub - litb 5/01

Respostas:

2

Minha pergunta é se todos os usos de modelos em C ++ são categorizados como metaprogramação.

Não.

Nem todos os usos de modelos, em C ++, são metaprogramadores.

Obviamente, é uma questão de definições, mas, em C ++, "metaprogramação" é sinônimo de "computação em tempo de compilação".

Portanto, com modelos, fazemos metaprogramação (especificamente metaprogramação de modelo), mas nem todos os usos de modelos são metaprogramação.

Um contra-exemplo simples

template <typename K, typename V>
void printKeyVal (K const & k, V const & v)
 { std::cout << k << ": " << v << std::endl; }

O anterior printKeyVal()é uma função de modelo que imprime, na saída padrão (portanto, em tempo de execução, não em tempo de compilação), alguns valores genéricos.

Ele não pode ser executado em tempo de compilação, portanto é "modelo", mas não é "metaprogramador".

Mais em geral: std::vectoré uma classe de modelo que usa alocação de memória. E a alocação de memória (até C ++ 17; talvez no futuro possa ser diferente) não pode ser usada no código em tempo de compilação.

Portanto std::vector(ao contrário std::arraydisso, ter um tamanho fixo, não usa alocação de memória) é um recurso de modelo que não pode ser usado (quando o uso envolve a instanciação de um std::vectorobjeto) para metaprogramação.

max66
fonte
Ainda assim, qualquer função que dependa do modelo requer pelo menos alguma metaprogramação. No seu exemplo, isso printKeyValé definido durante o tempo de compilação, de acordo com os argumentos do modelo
SomeWittyUsername
Quando você programa, você escreve código. Você não "calcula" as coisas. Então, eu definiria "metaprogramação" como "escrever código para escrever código". E é exatamente disso que trata cada modelo. Estou ciente de que a metaprogramação de modelos é frequentemente usada para o "cálculo do tempo de compilação" -, mas eu pessoalmente usaria um termo diferente para isso (tenho certeza de que não fiz isso no passado, desculpe-me).
Johannes Schaub - litb 5/01
@ JohannesSchaub-litb - É uma questão de idioma e definições (e eu tenho a desvantagem adicional de não conhecer bem o idioma inglês) e concordo que é possível uma definição de "metaprogramação" que inclua todos os modelos e talvez também razoável. O que digo é que, na comunidade C ++, o termo "metaprogramação" é usado com um significado diferente que se cruzam, mas não inclui todos os usos de modelo. Talvez eu esteja errado ... poderia ser uma enquete interessante.
max66 5/01
Talvez seja chamado de "metaprogramação" apenas se o código do modelo não for mais duplicado 1: 1 para cada tipo, porque se for duplicado 1: 1, o código do modelo será puramente passivo e toda a "metaprogramação" é feita pelo compilador . Se houver alguma especialização ou despacho estático ou de sobrecarga ou algo assim, é o próprio código que decide o que será gerado. Esta parece ser a posição de D
Johannes Schaub - litb
@SomeWittyUsername - Parece-me que você está usando uma definição de "metaprogramação" que, perfeitamente legítima e talvez também razoável, seja diferente da que a comunidade C ++ é, de fato, usando: rougly talking: "metaprogramming == compilar execução em tempo ". Talvez eu esteja errado e a comunidade use principalmente uma definição que inclua todos os modelos de uso ... poderia ser uma pesquisa interessante, suponho.
max66 5/01
1

O que é TMP em C ++?

A metaprogramação de modelos (TMP) em C ++ é uma técnica para expressar e executar algoritmos arbitrários em tempo de compilação usando modelos C ++. Geralmente é habilitado pelo uso da especialização de modelo para emular ramificações condicionais e a definição de modelo recursivo para emular loops. O exemplo mais conhecido é uma computação fatorial em tempo de compilação:

template <unsigned int n>
struct factorial {
    // recursive definition to emulate a loop or a regular recursion
    enum { value = n * factorial<n - 1>::value };
};

// specialization that describes "break" condition for the recursion
template <>
struct factorial<0> { 
    enum { value = 1 };
};

que usa as duas técnicas mencionadas acima.

Muito mais comum, no entanto, é o uso de TMP para detecção e transformação de tipos, em vez de computação numérica real, por exemplo, um std::is_pointerutilitário padrão ( fonte ):

// generic definition that emulates "false" conditional branch
template<class T>
struct is_pointer_helper : std::false_type {};

// a specialization that emulates "true" conditional branch
template<class T>
struct is_pointer_helper<T*> : std::true_type {};

template<class T>
struct is_pointer : is_pointer_helper< typename std::remove_cv<T>::type > {};

A maioria dos utilitários fornecidos pelo cabeçalho type_traits padrão é implementada usando técnicas TMP.

Dado que os algoritmos TMP são expressas usando definições de tipo, vale a pena mencionar que TMP é uma forma de programação declarativa em que a lógica do cálculo é expresso sem o uso de demonstrações de fluxo de controle explícitas ( if, else, for, etc ...).

Todo o uso de modelos C ++ é uma metaprogramação?

A resposta curta é: Não. Se os modelos não são usados ​​para expressar um algoritmo em tempo de compilação, não é uma metaprogramação, é uma programação genérica .

O objectivo principal para a introdução de modelos em C ++ foi para permitir a programação genérico, que é o de permitir reutilizar os mesmos algoritmos ( find, copy, sort, etc ...) e as estruturas de dados ( vector, list, map, etc ...) para quaisquer tipos, incluindo pelo utilizador definidos, que satisfazem certos requisitos.

De fato, o TMP em C ++ foi descoberto por acidente e não era o uso pretendido de modelos.


Em resumo: A metaprogramação de modelos em C ++ é o uso de modelos para expressar um algoritmo em tempo de compilação, a maioria (todos?) Dos outros usos de modelos C ++ é uma forma de programação genérica.

r3mus n0x
fonte
0

Estou tentando entender o que é metaprogramação geral e o que é em C ++ em particular

Você ainda não disse o que entende por metaprogramação em geral , para que suas respostas não tenham um ponto de partida comum.

Vou assumir que a definição da Wikipedia é boa o suficiente para isso:

A metaprogramação é uma técnica de programação na qual os programas de computador podem tratar outros programas como dados.

... pode ser usado para mover cálculos de tempo de execução para tempo de compilação, para gerar código usando cálculos de tempo de compilação ...

O C ++ geralmente não permite código auto-modificável, então estou ignorando isso. Também estou optando por não contar o pré-processador, pois a substituição de texto no (ou provavelmente antes) tempo de compilação não é o mesmo que operar na semântica do programa.

Minha pergunta é se todos os usos de modelos em C ++ são categorizados como metaprogramação

Não não é.

Considere, para referência:

#define MAX(a,b) ((a) > (b) ? (a) : (b))

que é vagamente a maneira de escrever uma função genérica ( maxindependente de tipo) sem usar modelos. Eu já disse que não conto o pré-processador como metaprogramação, mas, em qualquer caso, ele sempre produz código idêntico sempre que é usado.

Ele simplesmente delega a análise desse código e a preocupação com os tipos e se a>bestá definido para o compilador, em uma fase posterior da tradução . Nada aqui opera em tempo de compilação para produzir código resultante diferente dependendo de ... qualquer coisa. Nada, em tempo de compilação, é calculado.

Agora, podemos comparar a versão do modelo:

template <typename T>
T max(T a, T b) { return a > b ? a : b; }

Isso não realiza simplesmente uma substituição textual. O processo de instanciação é mais complexo, regras de sobrecarga de nomes e sobrecargas podem ser consideradas e, em certo sentido, instâncias diferentes podem não ser textualmente equivalentes (por exemplo, um pode ser usado bool ::operator< (T,T)e um bool T::operator<(T const&)ou o que for).

No entanto, o significado de cada instanciação é o mesmo (assumindo definições compatíveis operator<para tipos diferentes etc.) e nada foi computado no tempo de compilação, exceto o processo (mecânico) usual do compilador de resolver tipos e nomes e assim por diante.

Como um aparte, definitivamente não é suficiente que seu programa contenha instruções para o compilador dizer o que fazer , porque é isso que é toda a programação.

Agora, existem casos marginais como

template <unsigned N>
struct factorial() { enum { value = N * factorial<N-1>::value }; };

que faz mover um cálculo de tempo de compilação (e neste caso, um não-encerramento uma vez que não pode ser incomodado para escrever o caso terminal), mas sem dúvida são não metaprogramming.

Mesmo que a definição da Wikipedia mencionasse mover cálculos para compilar tempo, isso é apenas um cálculo de valor - não está tomando uma decisão em tempo de compilação sobre a estrutura ou semântica do seu código.

Sem utilidade
fonte
-1

Ao escrever funções C ++ com modelos, você está escrevendo "instruções" para o compilador dizer o que fazer ao encontrar chamadas da função. Nesse sentido, você não está escrevendo código diretamente, portanto, chamamos de metaprogramação.

Então, sim, todo código C ++ envolvendo modelos é considerado metaprogramação

Observe que apenas as partes que definem funções ou classes de modelos são metaprogramação. Funções e classes regulares são categorizadas como C ++!

Xatyrian
fonte
1
Quando digito "cp a.txt b.txt" no Bash, isso não está programado, embora eu esteja usando um ambiente de programação completo. Da mesma forma, quando uso std::vector, instruo um compilador a produzir um programa (por isso é meta), mas a instrução em si dificilmente é um programa. A maioria das pessoas não considera o uso de macros "metaprogramação".
n. 'pronomes' m.
1
Você responde está simplesmente errado! Por favor, leia as outras respostas fornecidas neste tópico para obter um entendimento básico do que significa MTP!
Klaus
1
Sempre que você escreve C ++ sem modelos, você está escrevendo instruções para o compilador. Então, o fato de que modelos de dizer ao compilador o que fazer, não pode ser suficiente para distinguir a programação de metaprogramming
Useless
1
@ JohannesSchaub-litb No contexto de C ++, o termo "metaprogramação" tem um significado específico que difere de seu significado geral . IIRC referiu-se inicialmente ao recurso C ++ descoberto cunhado por A.Alexandrescu em seu livro Modern C ++ Design . O uso clássico de modelo em C ++ não é metaprogramação (a menos que você use a metaprogramação não C ++).
YSC
1
Da pergunta do OP: "Estou tentando entender o que é metaprogramação geral e o que é em C ++ em particular" . Então, acho que seu ângulo é bom e constituiria uma excelente resposta. Mas este não é. -1
YSC