6

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.

rual93
  • 553
  • 4
  • 11
  • Please show us what does not work and the error message you got – Denis Sheremet May 14 '18 at 10:34
  • 6
    `std::complex`: "The effect of instantiating the template complex for any other type (than float, double, long double) is unspecified.". What do you want to achieve? – Stephan Lechner May 14 '18 at 10:36
  • 3
    If you want to use `std::complex`, you are going to need to explicitly specialize it to the fullest. It's not worth it, at all. – StoryTeller - Unslander Monica May 14 '18 at 11:40
  • I don't want to redefine int. This is just an example, I wanted to create my own scalar type and make it work with std::complex. However I faced this problem and I want to understand why I have that error. If I do `std::complex ci = 4;` I have `error: conversion from 'int' to non-scalar type 'std::complex' requested` Instead this works: `std::complex ci = (my_int) 4;` – rual93 May 14 '18 at 15:23
  • I am interested in why the user defined conversion is not applied, not about the problem with the complex and the types – rual93 May 14 '18 at 15:35
  • 1
    Your code on line 25 is attempting to convert from int to std::complex. On line 12 you've written a cast operator for int to my_int, but that is something different. In any case, std::complex may be a bad example to choose because the implementation is only required to allow float, double or long double (due to the intended correspondence with complex in the C standard) re: https://en.cppreference.com/w/cpp/numeric/complex – KarlM May 14 '18 at 21:29
  • @KarIM, I am interested in the reason why the used-defined conversion is not applied in copy initialization. Because what you say is not true for direct initialization. I think choosing std::complex is bad example because everybody is telling me about the fact that it is intended to be used only with float, double or long double and otherwise it is unspecified, this is not what I asked but thank you anyway. – rual93 May 15 '18 at 09:16

2 Answers2

2

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;
Eduard Rostomyan
  • 7,050
  • 2
  • 37
  • 76
1

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.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • You said **user-defined conversions are not allowed in the copy-initialization** Can you give me a reference about this? This is what I am interested in. – rual93 May 14 '18 at 15:34
  • @rual93 Edited. To be more precise, it is **more than one** user-defined conversion that is not allowed. – xskxzr May 14 '18 at 16:31
  • Thank you, this is what I wanted to know – rual93 May 15 '18 at 09:18