Pular para o conteúdo principal

Do macro ao template

Uma coisa que gera discussões acirradas dentre as pessoas nestes tempos mais modernos do C++ é o uso de macros.

Dentre os argumentos contra as macros estão os de que o uso de macros leva a criação de uma nova linguagem (o que é bem verdade quando usado sem moderação).

Quando se está desenvolvendo em C muitas coisas acabam sendo feitas usando macro por não termos estruturas genéricas para resolver problemas.



Para que a estrutura possa receber int ou double ou seja lá qual tipo numérico, eu preciso usar macro.

https://gist.github.com/thiagomg/3599dd59ff6bd7632fd4

A alternativa para C++ é bem conhecida => templates!

Os templates fornecem uma forma type-safe, em compile-time, de se implementar as mesmas rotinas, de forma tão eficiente quanto a macro e com validação sintática feita pelo compilador.

No primeiro exemplo, T é o container (vector, list, forward_list, etc) e U é o tipo de dados value_type do container.

Já no accumulate, temos uma pegadinha:

https://gist.github.com/thiagomg/608c1e50eee63836de1d

Reparem o auto no retorno e a declaração da variável ret. A declaração typename T::value_type é um define interno do container que exporta o tipo de dados que ele aloca internamente. Por não saber se o dado interno é um int ou algo como MeuUltraMegaHugeDouble, não podemos colocar ret = 0, mas usamos o inicializador padrão {}.

Bom, claro que temos containers da stdlib para facilitar a nossa vida

https://gist.github.com/thiagomg/42f0b8632dbbb8484953

E só para não dizer que não temos um bom caso para o macro:

https://gist.github.com/thiagomg/13f49494c09f0989de71

Desta forma, uma chamada de LOG_INFO("msg received: %s", msg->toString()) não resolverá o toString caso o nível de log info não esteja ativo.

Minha regra de ouro pessoal: Se possível evitar a macro, evite.

Código: https://github.com/SimplyCpp/examples/blob/master/macro_templ.cpp

Comentários

Postagens mais visitadas deste blog

Mestre Iota

Iota é a nona letra do alfabeto grego, ela é equivalente à letra i do nosso alfabeto. Por convenção ou hábito, utilizamos a letra i na programação para indicar algum tipo de incrementador, como por exemplo, em um for-loop . https://gist.github.com/fabiogaluppo/a23894ae743f7dd29274 Curiosamente, iota , como identificador, também é utilizado na programação para indicar uma sequência finita e consecutiva de números inteiros, como por exemplo, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. Inclusive, originalmente na STL existia a função iota , inspirada pela linguagem de programação APL , você pode conferir neste link: http://www.sgi.com/tech/stl/iota.html

Valores Aleatórios Simplificados

A partir do C++ 11, foi introduzido o header <random>  com diversos facilitadores para suporte de geração de números aleatórios. A produção destes números é feita através da combinação de duas categorias de objetos: os geradores e os distribuidores. Os geradores, são responsáveis pela geração dos números, e os distribuidores são responsáveis pela transformação dos números gerados em algum tipo de distribuição de probabilidade.  Como por exemplo, uma distribuição normal (aquela da Gaussiana) ou uma distribuição de Pareto (aquela do 80-20). As opções não faltam, como você pode ver nas referências, por exemplo:   http://www.cplusplus.com/reference/random/ ou  http://en.cppreference.com/w/cpp/header/random .

Policy-based design: log writer

Policy-based design Vamos neste artigo dar mais uma pincelada no Policy-based design . Vamos fazer como exemplo uma classe de log. Como este é só um exemplo, não vamos considerar múltiplos parâmetros no log, mas somente uma string, assim não fugiremos do assunto. Uma das coisas mais importantes neste tipo de design é o desacoplamento. Ele é uma excelente alternativa ao uso de interfaces por duas razões: Não gera chamadas virtuais (ou um nível de indireção em tempo de execução) Duck typing ( https://pt.wikipedia.org/wiki/Duck_typing ) Eu gosto bastante desse tipo de design, já usado aqui: http://simplycpp.com/2016/02/05/leitura-de-configuracao-em-c/