Tenho escrito alguns testes para aritmética de números complexos.
Tentei escrevê-los de uma forma em que não preciso reescrever uma seção de código para cada operador. Estou tentando armazenar std::complex
operadores sobrecarregados como operator+
, operator+=
, operator-
, operator-=
em uma std::function
variável. A razão pela qual preciso dos std::complex
operadores é porque preciso verificá-los em relação à minha própria implementação de números complexos.
No entanto, não consigo fazê-lo funcionar, principalmente porque parece haver uma incompatibilidade entre o tipo da variável ( std::function
) e o tipo do valor ( std::complex
operadores). Como devo escrever o código para poder armazenar essas funções de operador em uma std::function
variável?
Esta é minha tentativa, mas infelizmente não funciona:
std::function<void(std::complex<double>&, const std::complex<double>&)> var =
&std::complex<double>::operator+=;
Use uma expressão lambda:
Note que
operator+=
não retornavoid
. Para manter a semântica de+=
altere o lambda parareturn a+=b;
e especifique seu tipo de retorno comostd::complex<double>&
.Existem
<functional>
objetos de função genéricos para quase todos os operadores C++, atribuição ecxept e suas contrapartes compostas, addressof, dereference e index:Entretanto, para operadores com classes std ausentes, você precisa usar lambdas:
funções e funções membro definidas na biblioteca padrão e suas classes têm tipos não especificados. Elas apenas carregam o nome de função e não devem ser assumidas como estritamente funções. Como tal, tentar armazenar seus endereços como ponteiros de função da velha escola é UB.
No meu último snippet, primeiro defini um lambda genérico nomeado, então inicializei um
std::function
com esse lambda. Isso torna possível comparar de forma confiável instâncias destd::function
usando suatarget
função de template de membro:Se um lambda sem nome fosse usado, tal teste não estaria disponível. Porque cada instância lambda tem um identificador de tipo distinto exclusivo.
Você deve verificar a documentação do
std::complex::operator+=
.Observe que a versão do modelo tem apenas uma sobrecarga:
que não corresponde ao seu caso (você está esperando o tipo de argumento
const std::complex<T>&
).Agora, se você der uma olhada mais abaixo no documento, verá outra versão de modelo de
operator+=
:Então você precisa disto para que funcione:
Observe o extra
<double>
!https://godbolt.org/z/TPGMe435s
Observe que esse operador também deve funcionar ao adicionar
std::complex
com diferentes tipos de base, é por isso que o modelo de função membro é necessário, entãostd::complex<float>
elestd::complex<double>
pode ser adicionado.