I would like to know how I should define the class my_int so that the cast from int to std::complex< my_int >
is done by the compiler instead of manually by me.
The following program does not compile if 4 is not casted to "my_int
"
// Example program
#include <iostream>
#include <string>
#include <complex>
struct my_int
{
my_int() : _i(0) {}
my_int(const my_int& mi) : _i(mi._i) {}
my_int(int i) : _i(i) {}
operator int(){return _i;}
int _i;
};
std::ostream& operator<<(std::ostream& os, const my_int& mi)
{
os << mi._i;
return os;
}
int main()
{
std::complex<my_int> ci = 4; // Casting 4 to my_int works
std::cout << ci;
}
I know that if you initialize ci
with std::complex<my_int> ci(4)
it works, but I want it to work with copy initialization.
The initializer for a scalar (an object of integer type including booleans and enumerated types, floating type including complex and imaginary, and pointer type including pointer to function) must be a single expression, optionally enclosed in braces, or an empty initializer (since C23) :
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T 's constructor.
There is no such term as move-initialization. Implicit conversion is defined in terms of copy-initialization: if an object of type T can be copy-initialized with expression E, then E is implicitly convertible to T . The equals sign, =, in copy-initialization of a named variable is not related to the assignment operator.
See initialization for the rules that apply when no initializer is used. As with all other initializations, expression must be a constant expression when initializing objects of static or thread-local storage duration .
You can define you complex class and write the constructor this way.
Complex(int re, int im = 0);
In this case the compiler will implicitly convert int to complex on
Complex c = 5;
The seeming problem is that more than one user-defined conversion is not allowed in the copy-initialization context, and it can be solved by using direct-initialization context, e.g.
std::complex<my_int> ci{4};
However, there is another hidden problem: the effect of instantiating the template complex for any type other than float
, double
or long double
is unspecified, so you have to explicitly specialize it, as StoryTeller pointed out in the comment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With