sábado, 19 de julho de 2008

C++: Link Error

A linguagem C++ é fascinante. As vezes um pouco confusa, com todos sabem. Dá um certo trabalho fazer código direito. Talvez isso seja parte motivo para orgulho que eu sinto quando termino um projeto. Pessoalmente acho que a linguagem poderia melhorar, mas como está é aceitável.

O que não é aceitável é a forma como o linkeditor mostra mensgens de erro. Em alguns ambientes, como o VS.NET, eu não tenho nem informação de onde o erro corre. Eu tenho um projeto que está começando, com cerca de 50 arquivos, usando templates (em linguagens com suporte a reflexão seriam chamados de generics). Uma das mensagens de erro que apareceram durante o desenvolvimento foi:



O problema com o código já foi resolvido. A questão é: Alguém nesse mundo consegue ter alguma idéia de qual é o erro olhando apenas para isso? Tipicamente a mensagem de erro é suficiente para saber que esquecemos um ponto-e-vírgula, algum parâmetro de uma função está errado, o nome de algum método não está escrito corretamente ou alguma coisa assim. A eficiência do compilador de nos dizer o que está errado tem grande influência na produtividade. E nesse caso? Eu programo pouco com C++, menos ainda usando templates. As vezes levo cerca de 2 horas para corrigir um problema desses com o VS.NET.

Vou dizer uma coisa ridícula: O compilador de C++ do Visual Studio não adquiriu qualidade profissional a ponto de poder ser usado em ambiente de produção para código que envolva templates. Melhorias necessárias:

1. O linker deve mostrar a linha onde um erro acontece. Sei que isso é possível por que o eclipse com g++ faz. No entanto eu ainda não consegui classes template friend com ele, e no VS.NET funciona;

2. Os erros de linkedição relacioandos a template precisam ser totalmente revistos. Se uma instância de uma classe template possui um método que espera um tipo genérico e eu passo um tipo errado mensagem de erro deve ser semelhante a mensagem de quando eu passo um parâmetro incorreto para uma classe não-template;

3. O compilador precisa suportar o keyword export.
Suponha que eu tenha uma classe template List. Se essa classe for definida em um arquivo .h e implementada em um cpp eu tenho dois problemas: Não consigo usar a velha técnica de fornecer uma biblioteca de classes compiladas em .obj para meus clientes juntamente com os arquivos .h. Este problema nunca me incomodou muito até agora. O segundo problema me incomoda em 100% dos casos. Para usar a classe Lista eu posso fazer:


#include "Lista.h"
#include "Lista.cpp"

Lista *lista = new Lista();


Eu incluí o arquivo cpp por que o texto da implementação tem que estar disponível por um motivo muito chato de detalhar. Se eu tiver um segundo arquivo de também usa esta lista para strings eu tenho um erro extremamente confuso do linkeditor. O texto do erro certamente não ajuda muito a resolver o problema (para variar). Eu sou obrigado vender minha alma para o diabo do #ifdef. E como todos sabem, quem usa #ifdef vai para o mesmo inferno que os spammers.

A solução da linguagem é colocar o keyword export na definição da classe. Isso deveria resolver todos os problemas. No entanto tanto g++ quanto VS.NET não suportam essa keyword.

Eu acho que a Microsoft está no caminho certo. Mais alguns anos de desenvolvimento e eles podem acabar chegando em um compilador descente. E então eles podem até, imaginem só, reescrever todos os outros programas de forma decente. Do zero, em boa parte dos casos.