Eu quero passar uma função sobrecarregada para o std::for_each()
algoritmo. Por exemplo,
class A {
void f(char c);
void f(int i);
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), f);
}
};
Eu esperaria que o compilador resolvesse f()
pelo tipo de iterador. Aparentemente, ele (GCC 4.1.2) não faz isso. Então, como posso especificar qual f()
eu quero?
Respostas:
Você pode usar
static_cast<>()
para especificar qualf
usar de acordo com a assinatura da função implícita no tipo de ponteiro de função:Ou, você também pode fazer isso:
Se
f
for uma função membro, você precisará usarmem_fun
, ou para o seu caso, a solução apresentada neste artigo do Dr. Dobb .fonte
f()
é um membro de uma classe (veja o exemplo editado acima)reinterpret_cast
. Na maioria das vezes, vejo elencos em estilo C usados para isso. Minha regra é que os lançamentos nos ponteiros de função são perigosos e desnecessários (como mostra o segundo trecho de código, existe uma conversão implícita).std::for_each(s.begin(), s.end(), static_cast<void (A::*)(char)>(&A::f));
Lambdas para o resgate! (observação: C ++ 11 obrigatório)
Ou usando decltype para o parâmetro lambda:
Com lambdas polimórficas (C ++ 14):
Ou desambique removendo a sobrecarga (funciona apenas para funções gratuitas):
fonte
mem_fn
ebind
, que BTW. Também é C ++ 11). Além disso, se queremos ser realmente pedantes,[&](char a){ return f(a); }
são 28 caracteres estatic_cast<void (A::*)(char)>(&f)
35 caracteres.Por que isso não funciona?
Seria ótimo se fosse esse o caso! No entanto,
for_each
é um modelo de função, declarado como:A dedução de modelo precisa selecionar um tipo para
UnaryFunction
no ponto da chamada. Masf
não tem um tipo específico - é uma função sobrecarregada, existem muitosf
s com tipos diferentes. Atualmente, não existe uma maneira defor_each
auxiliar o processo de dedução de modelo, indicando o quef
ele deseja; portanto, a dedução de modelo simplesmente falha. Para que a dedução do modelo seja bem-sucedida, você precisa trabalhar mais no site de chamada.Solução genérica para corrigi-lo
Entrando aqui alguns anos e C ++ 14 depois. Em vez de usar a
static_cast
(que permitiria a dedução do modelo com êxito "corrigindo" o quef
queremos usar, mas requer que você execute manualmente a resolução de sobrecarga para "corrigir" a correta)), queremos fazer o compilador funcionar para nós. Queremos chamarf
alguns argumentos. Da maneira mais genérica possível, é isso:É muito difícil digitar, mas esse tipo de problema surge irritantemente com frequência, para que possamos apenas envolvê-lo em uma macro (suspiro):
e então apenas use:
Isso fará exatamente o que você deseja que o compilador faça - execute a resolução de sobrecarga no
f
próprio nome e faça a coisa certa. Isso funcionará independentemente def
ser uma função livre ou uma função de membro.fonte
Não para responder à sua pergunta, mas eu sou o único que acha
mais simples e mais curto que a
for_each
alternativa sugerida por in silico neste caso?fonte
O problema aqui parece não ser a resolução de sobrecarga, mas na verdade a dedução dos parâmetros do modelo . Embora a excelente resposta do @In silico resolva um problema ambíguo de sobrecarga em geral, parece que a melhor solução ao lidar com
std::for_each
(ou similar) é especificar explicitamente seus parâmetros de modelo :fonte
Se você não se importa em usar o C ++ 11, aqui está um ajudante inteligente que é semelhante (mas menos feio que) ao elenco estático:
(Funciona para funções-membro; deve ser óbvio como modificá-lo para funcionar em funções independentes, e você deve poder fornecer as duas versões e o compilador selecionará a correta para você.)
Agradecemos a Miro Knejp por sugerir: consulte também https://groups.google.com/a/isocpp.org/d/msg/std-discussion/rLVGeGUXsK0/IGj9dKmSyx4J .
fonte
R
, não é deduzido. Também não há menção a isso nesta resposta.R
, estou fornecendoArgs
.R
eT
são deduzidos. É verdade que a resposta poderia ser melhorada. (Não existeT
no meu exemplo, porém, porque não é um membro do ponteiro-to-, porque isso não iria funcionar comstd::for_each
.)