Existe alguma maneira de obter sobrecarga de função em C? Eu estou olhando para funções simples para serem sobrecarregadas como
foo (int a)
foo (char b)
foo (float c , int d)
Eu acho que não há caminho direto; Estou procurando soluções alternativas, se houver alguma.
c
overloading
FL4SOF
fonte
fonte
Respostas:
Existem poucas possibilidades:
fonte
Sim!
Desde que essa pergunta foi feita, o padrão C (sem extensões) ganhou efetivamente suporte para sobrecarga de funções (não operadores), graças à adição da
_Generic
palavra - chave em C11. (suportado no GCC desde a versão 4.9)(A sobrecarga não é realmente "incorporada" da maneira mostrada na pergunta, mas é muito fácil implementar algo que funciona dessa maneira.)
_Generic
é um operador de tempo de compilação na mesma família quesizeof
e_Alignof
. É descrito na seção 6.5.1.1 padrão. Ele aceita dois parâmetros principais: uma expressão (que não será avaliada em tempo de execução) e uma lista de associação de tipo / expressão que se parece um pouco com umswitch
bloco._Generic
obtém o tipo geral da expressão e, em seguida, "alterna" para selecionar a expressão do resultado final na lista para seu tipo:A expressão acima é avaliada como
2
- o tipo da expressão de controle eint
, portanto, escolhe a expressão associadaint
como o valor. Nada disso permanece em tempo de execução. (Adefault
cláusula é opcional: se você a deixar desativada e o tipo não corresponder, isso causará um erro de compilação.)A maneira como isso é útil para a sobrecarga de funções é que ela pode ser inserida pelo pré-processador C e escolher uma expressão de resultado com base no tipo de argumentos transmitidos para a macro de controle. Então (exemplo do padrão C):
Essa macro implementa uma
cbrt
operação sobrecarregada , despachando o tipo de argumento para a macro, escolhendo uma função de implementação apropriada e passando o argumento da macro original para essa função.Então, para implementar seu exemplo original, poderíamos fazer o seguinte:
Nesse caso, poderíamos ter usado uma
default:
associação para o terceiro caso, mas isso não demonstra como estender o princípio a vários argumentos. O resultado final é que você pode usarfoo(...)
seu código sem se preocupar (muito [1]) com o tipo de argumento.Para situações mais complicadas, por exemplo, funções que sobrecarregam um número maior de argumentos ou números variáveis, você pode usar macros de utilitário para gerar automaticamente estruturas de despacho estáticas:
( implementação aqui ) Portanto, com algum esforço, você pode reduzir a quantidade de clichê para parecer uma linguagem com suporte nativo para sobrecarga.
Como um aparte, já era possível sobrecarregar o número de argumentos (não o tipo) em C99.
[1] observe que a maneira como C avalia os tipos pode enganá-lo. Isso escolherá
foo_int
se você tentar passar um literal de caractere, por exemplo, e precisar mexer um pouco se quiser que suas sobrecargas suportem literais de string. Ainda bem legal no geral.fonte
Como já foi dito, a sobrecarga no sentido em que você quer dizer não é suportada por C. Um idioma comum para resolver o problema é fazer com que a função aceite uma união marcada . Isso é implementado por um
struct
parâmetro, em que ostruct
próprio consiste em algum tipo de indicador de tipo, como umenum
, e umunion
dos diferentes tipos de valores. Exemplo:fonte
whatever
s em funções separadas (set_int
,set_float
, etc). Em seguida, "marcar o tipo" se torna "adicione o nome do tipo ao nome da função". A versão nesta resposta envolve mais digitação, mais custo de tempo de execução, mais chances de erros que não serão detectados no momento da compilação ... Não vejo nenhuma vantagem em fazer as coisas dessa maneira! 16 votos positivos ?!Aqui está o exemplo mais claro e conciso que encontrei demonstrando sobrecarga de função em C:
https://gist.github.com/barosl/e0af4a92b2b8cabd05a7
fonte
Se o seu compilador é o gcc e você não se importa de fazer atualizações manuais toda vez que adiciona uma nova sobrecarga, você pode fazer alguma macro mágica e obter o resultado desejado em termos de chamadas, não é tão bom escrever ... mas é possível
observe __builtin_types_compatible_p e use-o para definir uma macro que faça algo como
mas sim desagradável, apenas não
EDIT: C1X estará recebendo suporte para expressões genéricas de tipo com a seguinte aparência:
fonte
Sim, mais ou menos.
Aqui você vai por exemplo:
Ele produzirá 0 e Olá. De printA e printB.
fonte
A abordagem a seguir é semelhante à de a2800276 , mas com alguma macro mágica C99 adicionada:
fonte
Isso pode não ajudar em nada, mas se você estiver usando o clang, poderá usar o atributo sobrecarregável - Isso funciona mesmo ao compilar como C
http://clang.llvm.org/docs/AttributeReference.html#overloadable
Cabeçalho
Implementação
fonte
No sentido que você quer dizer - não, você não pode.
Você pode declarar uma
va_arg
função comovoid my_func(char* format, ...);
, mas você precisará passar algum tipo de informação sobre o número de variáveis e seus tipos no primeiro argumento, como
printf()
faz.fonte
Normalmente, uma verruga para indicar o tipo é anexada ou anexada ao nome. Você pode se safar das macros em alguns casos, mas isso depende do que você está tentando fazer. Não há polimorfismo em C, apenas coerção.
Operações genéricas simples podem ser feitas com macros:
Se o seu compilador suportar typeof , operações mais complicadas poderão ser colocadas na macro. Você pode ter o símbolo foo (x) para oferecer suporte à mesma operação em diferentes tipos, mas não pode variar o comportamento entre diferentes sobrecargas. Se você quiser funções reais em vez de macros, poderá colar o tipo no nome e usar uma segunda colagem para acessá-lo (eu não tentei).
fonte
A resposta de Leushenko é muito legal - apenas: o
foo
exemplo não é compilado com o GCC, que falhafoo(7)
, tropeçando naFIRST
macro e na chamada de função real ((_1, __VA_ARGS__)
permanecendo com uma vírgula excedente. Além disso, estamos com problemas se queremos fornecer sobrecargas adicionais , comofoo(double)
.Então, decidi elaborar a resposta um pouco mais, inclusive para permitir uma sobrecarga vazia (
foo(void)
- o que causou alguns problemas ...).A idéia agora é: Defina mais de um genérico em diferentes macros e deixe selecionar o correto de acordo com o número de argumentos!
O número de argumentos é bastante fácil, com base nesta resposta :
Isso é legal, resolvemos um
SELECT_1
ouSELECT_2
(ou mais argumentos, se você quiser / precisar deles), por isso precisamos de definições apropriadas:OK, já adicionei a sobrecarga vazia - no entanto, essa não é realmente coberta pelo padrão C, que não permite argumentos variados vazios, ou seja, confiamos nas extensões do compilador !
No começo, uma chamada de macro vazia (
foo()
) ainda produz um token, mas um vazio. Portanto, a macro de contagem realmente retorna 1 em vez de 0, mesmo na chamada de macro vazia. Podemos "facilmente" eliminar esse problema, se colocarmos a vírgula após__VA_ARGS__
condicionalmente , dependendo da lista estar vazia ou não:Que parecia fácil, mas a
COMMA
macro é muito pesado um; felizmente, o tópico já foi abordado em um blog de Jens Gustedt (obrigado, Jens). O truque básico é que as macros de função não são expandidas se não forem seguidas por parênteses, para obter mais explicações, dê uma olhada no blog de Jens ... Só precisamos modificar as macros um pouco para nossas necessidades (vou usar nomes mais curtos e menos argumentos por brevidade).E agora estamos bem ...
O código completo em um bloco:
fonte
Você não pode simplesmente usar C ++ e não usar todos os outros recursos de C ++, exceto este?
Se ainda não houver apenas C estrito, eu recomendaria funções variadas .
fonte
Tente declarar essas funções como
extern "C++"
se o seu compilador suporta isso, http://msdn.microsoft.com/en-us/library/s6y4zxec(VS.80).aspxfonte
Espero que o código abaixo o ajude a entender a sobrecarga de funções
fonte