paulo1205
(usa Ubuntu)
Enviado em 27/04/2016 - 10:56h
Obrigado pela correção. Provavelmente, com o C++11, esse novo header foi introduzido no mundo C++. Antes dele, nem teria como, pois ele surgiu no C, oficialmente, apenas em 1999 (com o padrão ISO/IEC 9899:1999, o C99), e o padrão ISO para o C++ foi anterior a isso, em 1998.
Sem necessariamente querer me justificar, mas justificando-me mesmo assim, note que há ainda sites que dizem a mesma coisa que eu disse. Por exemplo, se você procurar por “tgmath.h” na WIkipedia em Inglês, verá que o artigo que AINDA está lá, cujo texto vem desde 24 de outubro de 2012 (e que não foi escrito por mim), fala literalmente isto (grifos meus):
The C++ language includes native support for function overloading and thus does not provide the tgmath.h header even as a compatibility feature .
Provavelmente tal artigo precisa ser atualizado. Mas o comentário fazia sentido no C++98: não havia como oferecer compatibilidade com algo que ainda não tinha sido inventado.
No meu entendimento, o <ctgmath> não faz muito sentido mesmo em C++11. Eis por quê:
1) O “tg” no nome do cabeçalho vem da abreviação de “
type generic ”. E embora essa generalidade de tipos fosse uma coisa nova no C99, no C++ já era coisa corriqueira.
2) O <cmath>.já fazia praticamente tudo (se não absolutamente tudo) do que <tgmath.h> supostamente inventou.
3) O padrão corrente do C quando o C++11 foi lançado ainda era o C99 (o C11 saiu somente alguns meses depois do C++11). E o <tgmath.h> do C99 era uma excrecência até para muitos programadores de C (cf.
https://web.archive.org/web/20131205042841/http://carolina.mff.cuni.cz/~trmac/blog/2005/the-ugliest-... ,
http://www.pixelstech.net/article/1324906407-The-ugliest-C-feature%3A-%3Ctgmath-h%3E ), pois era um cabeçalho
mágico , que alterava o comportamento do compilador, mas que não podia ser escrito com nenhuma das construções sintáticas oferecidas pelo próprio C99, e implicava que cada compilador podia inventar seu próprio conjunto de truques internos para poder implementá-lo.
4) <tgmath.h> permite a
invocação de funções variadas com base no tipo dos argumentos, mas
não permitia seu uso como ponteiros de função . O código (tosco, mas só para dar uma ideia) abaixo, por exemplo, funciona em C++98 com <cmath>, mas não compila em C com <tgmath.h>, a não ser que eu escolha
double como tipo associado à macro
MY_FLOAT_TYPE .
#ifdef __cplusplus
#include <cmath>
usign namespace std;
#else
#include <tgmath.h>
#endif
// Eu posso trocar o tipo abaixo para double ou long double a cada compilação
#define MY_FLOAT_TYPE float
MY_FLOAT_TYPE f(int operation, MY_FLOAT_TYPE value){
MY_FLOAT_TYPE (*pf)(MY_FLOAT_TYPE);
switch(operation){
case 1: pf=cos; break;
case 2: pf=sin; break;
case 3: pf=sqrt; break;
default: pf=fabs;
}
return value*pf(value);
}
5) Criar um cabeçalho de compatibilidade vazio (ou que seja um mero apelido para outro) é um desperdício.
6) Se alguém decidir parar para converter um programa de C para C++, que faça uma conversão de verdade, em vez de mera adaptação meia-boca. Mesmo que ele use alguma ferramenta automática de conversão (leia-se “adaptação meia-boca”), a ferramenta certamente será programada de modo a saber que não necessariamente tudo que aparecer como <XXX.h> terá um correspondente na forma <cXXX>. Então a tal ferramenta poderia muito bem saber que o correspondente a <tgmath.h> é <cmath> (ou <cmath> mais <ccomplex>) em vez de <ctgmath>.
7) A comunidade em C até hoje não engoliu bem os movimentos feitos pelo comitê de padronização do C no sentido de introduzir recursos voltados exclusivamente à computação numérica, como de C fosse destinado a suplantar completamente o Fortran (foi por causa desse impulso que apareceu a canhestra <tgmath.h>). O curioso é que essas mudanças só causaram problemas: a comunidade C não gostou, criou incompatibilidades desnecessárias com C++, e a comunidade de computação científica, que seria a grande beneficiária da estratégia, simplesmente a ignorou (i.e. Fortran continuou reinando absoluto, e as iniciativas mais fortes de fazer algo em outras linguagens preferiu C++, Java, Python e linguagens de programação funcionais).
O C11 finalmente introduziu a palavra-chave
_Generic , que padronizou uma forma de selecionar tokens com base no tipo de uma expressão de controle (é uma solução horrível, mas pelo menos é algo padronizado). Com isso, <tgmath.h> passou finalmente a poder ser escrito e implementado em C (e com mais um monte de macros, que por si sós já deveriam provocar algum nível de alerta). Mas mesmo isso não resolveu a questão dos ponteiros de função.
Por fim, uma nota que provavelmente expõe um bug do GCC 4.8 (que acompanha o Ubuntu 14.04): seu <ctgmath> inclui apenas <cmath>, não <cmath> mais <ccomplex>, que é o que diz o padrão. Então, cabe ter cuidado com o uso disso.