admin管理员组文章数量:1410717
I've been writing some tests for the arithmetic of complex numbers.
I've tried to write them in a way where I don't have to rewrite a code section for each operator. I am trying to store std::complex
overloaded operators such as operator+
, operator+=
, operator-
, operator-=
in a std::function
variable. The reason why I need the std::complex
operators is because I need to check them against my own implementation of complex numbers.
However, I can't get it to work, mostly because there seems to be a mismatch between the type of the variable (std::function
) and the type of the value (std::complex
operators). How should I write the code so that I can store these operator functions in a std::function
variable?
This is my attempt, but alas it doesn't work:
std::function<void(std::complex<double>&, const std::complex<double>&)> var =
&std::complex<double>::operator+=;
I've been writing some tests for the arithmetic of complex numbers.
I've tried to write them in a way where I don't have to rewrite a code section for each operator. I am trying to store std::complex
overloaded operators such as operator+
, operator+=
, operator-
, operator-=
in a std::function
variable. The reason why I need the std::complex
operators is because I need to check them against my own implementation of complex numbers.
However, I can't get it to work, mostly because there seems to be a mismatch between the type of the variable (std::function
) and the type of the value (std::complex
operators). How should I write the code so that I can store these operator functions in a std::function
variable?
This is my attempt, but alas it doesn't work:
std::function<void(std::complex<double>&, const std::complex<double>&)> var =
&std::complex<double>::operator+=;
Share
edited Mar 5 at 18:03
Remy Lebeau
601k36 gold badges508 silver badges851 bronze badges
asked Mar 5 at 17:01
CuriousSoulCuriousSoul
432 bronze badges
3
|
3 Answers
Reset to default 4Use a lambda expression:
std::function<void(std::complex<double>&, const std::complex<double>&)> var =
[](std::complex<double>& a,const std::complex<double>& b) {
a+=b;
};
Note that operator+=
does not return void
. To keep the semantics of +=
change the lambda to return a+=b;
and specify its return type to be std::complex<double>&
.
Using <functional>
there are generic function objects for almost all C++ operators, ecxept assignment and its compound counterparts, addressof and dereference and index:
#include <functional>
#include <complex>
using complex_f = std::complex<float>;
using fn_t =
std::function<void(complex_f&, complex_f const&)>;
fn_t add_fn = std::plus<>{};
fn_t multiply_fn = std::multiplies<>{};
However for operators with missing std classes, you need use lambdas:
auto constexpr add_assign =
[](auto& dst, auto const& src)
->decltype(auto)
{ return dst += src; };
fn_t increase_fn = add_assign;
functions and member functions defined in standard library and its classes have unspecified types. They just bear the name of function, and should not be assumed to be strictly functions. As such, trying to store their addresses as old-school function pointers is UB.
In my last snippet, I first defined a named generic lambda, then initialize an std::function
with that lambda. This makes it possible to reliably compare instances of std::function
using its target
member template function:
auto const fn_tgt
= increase_fn.target<decltype(add_assign)>);
assert((nullptr!=fn_tgt);
If an unnamed lambda were used, such test wouldn't be available. Because every lambda instance has a unique distinct type identifier.
You should check the documentation of std::complex::operator+=
.
Note the template version has only one overload:
constexpr complex& operator+=( const T& other ); // (1)
which does not match your case (you are expecting argument type const std::complex<T>&
).
Now, if you take a look lower in the doc, you will see another template version of operator+=
:
template<class X>
constexpr complex& operator+=( const std::complex<X>& other ); // (5)
So you need this to make it work:
std::function<void(std::complex<double>&, const std::complex<double>&)> var =
&std::complex<double>::operator+=<double>;
Note the extra <double>
!
https://godbolt./z/TPGMe435s
Note that this operator should also work when adding std::complex
with different base types, that is why the template of member function is needed, so std::complex<float>
and std::complex<double>
could be added.
本文标签: functionHow to store stdcomplex operator as a variable (C)Stack Overflow
版权声明:本文标题:function - How to store std::complex operator as a variable (C++) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745018983a2638016.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
std::function<void(std::complex<double>&, const std::complex<double>&)> var = [](td::complex<double>& lhs, const std::complex<double>& rhs){ lhs += rhs; };
– Jarod42 Commented Mar 5 at 17:02operator +=
returns self BTW, and then it is trickier with lambda. you have to specify the return type, ordecltype(auto)
with appropriate expression. – Jarod42 Commented Mar 5 at 17:07std::plus
? (Depending on your operations, you may need to roll some of your own. Only some of the operators are provided this way, and I think that none of the "in place" (assigning) operators are provided.) – Eljay Commented Mar 5 at 17:15