2

Consider the sample code below:

#include <iostream>

using namespace std;

class dummy
{
   private:
      int y;

   public:
      dummy(int b = 0) : y(b) {
      }

      friend ostream& operator<<(ostream& os, const dummy& obj);
};

ostream& operator<<(ostream& os, const dummy& obj)
{
   os << obj.y;
   return os;
}

class sample
{
   private:
      int x;

   public:
      sample(int a = 0) : x(a)
      {
      }

      operator dummy()
      {
         dummy d(100);
         return d;
      }

      operator int()
      {
         return x;
      }
};

int main()
{
   sample ob1(5);
   dummy d;

   //d = ob1; //Line1  
   d = (dummy)ob1; //Line2

   cout << d << "\n";
}

In Line1, an implicit cast is done. I understand how the implicit casting works in this case. The compiler gives no errors.

But in Line2, an explicit cast of sample object is done to dummy object. But the compiler gives the following error.

error: call of overloaded `dummy(sample&)' is ambiguous

note: candidates are: dummy::dummy(const dummy&)

note: dummy::dummy(int)

Questions:

  1. Why is these errors occurring?

  2. I do not understand the meaning of the error messages. Why the candidate functions of dummy class mentioned in the errors?

nitin_cherian
  • 6,405
  • 21
  • 76
  • 127
  • 2
    possible duplicate of [Why constructor is not called for given casting operator?](http://stackoverflow.com/questions/6120240/why-constructor-is-not-called-for-given-casting-operator) – iammilind Feb 28 '12 at 05:26
  • Who ever voted to close this question does not know the importance of the question. Kindly look into the questions i have asked – nitin_cherian Feb 28 '12 at 05:33

1 Answers1

6

The line:

d = (dummy)ob1

attempts to do the following:

  1. Construct a dummy object from obj1
  2. Assign that temporary dummy object to d

Part 1 is what causes the problems. To construct the temporary dummy object the compiler must search for some way to convert obj1 into a type which a dummy can be constructed from. It finds that there are two ways to do this:

  1. Call operator int
  2. Call operator dummy

You do not tell it which one of these two alternatives you want it to take, and so the code is ambiguous.


Your problem could be recreated (with the extraneous parts removed) as follows:

struct t_1 {};
struct t_2 {};
struct sample {
    operator t_1() const{ return t_1(); }
    operator t_2() const{ return t_2(); }
};
void f(t_1) {}
void f(t_2) {}
int main() {
    sample obj1;
    //overload resolution will fail
    //disambiguate with f(obj1.operator t_1()) or f(obj1.operator t_2())
    f(obj1);
}
Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • Then why does the compiler does not complain for the implicit cast d=ob1? – nitin_cherian Feb 28 '12 at 05:37
  • 1
    `d=obj1` calls the assignment operator of `d`. There is no assignment operator for `d` which takes an `int` argument, and so only the `operator dummy` is considered. In the case of `(dummy)obj1` (which should be rewritten as `dummy(obj1)` for consistency with multi-argument constructors) a temporary object is constructed, but it is unclear whether the `int` or the `dummy const&` constructor should be used. – Mankarse Feb 28 '12 at 05:39
  • `operator int` and `operator dummy` are cast operators of class `sample`. But look at the candidate functions in the error message. They are referring to the class `dummy`. Why is that? – nitin_cherian Feb 28 '12 at 05:41
  • @LinuxPenseur: It is the fact that you are trying to construct a `dummy` which causes overload resolution to occur. There are two candidate constructors `dummy(int)` and `dummy(dummy const&)`. `obj1` can be implicitly converted to match either constructor, and so overload resolution fails. – Mankarse Feb 28 '12 at 05:47
  • There is no compilation error when i remove the `operator int` in the sample class. Why is that? Only when i add the `operator int` does the error occur – nitin_cherian Feb 28 '12 at 06:09
  • There is ambiguity because the compiler sees two functions it could all, and it has no way to chose between the two. It's no surprise that if you don't have one of those functions the compiler doesn't see an ambiguity. – Max Lybbert Feb 28 '12 at 06:33