ggrajeda
ggrajeda

Reputation: 13

Can the argument of a converting constructor be implicitly converted?

Right now I'm working on a project where convertibility between two classes (A and B) is highly desirable. I've created a function myFunc() that takes an object of class A as its argument, and I've passed it an object of class B.

The reason I expected this to work is that B can be implicitly converted to an integer, and A can be implicitly constructed with an integer. I expected these two processes to occur so that an object of class B would implicitly be converted to an object of class A. This was not the case.

When I try to pass in an object of class B to myFunc(), I get the error: error: could not convert 'b' from 'B' to 'A'.

Interestingly, however, I can pass in an object of class B that I explicitly cast to an integer, or an explicitly constructed object of class A which takes an object of class B as its argument. It seems that only one implicit process (whether it be a converting constructor or an implicit conversion) can happen in a single line. Why is this the case? Is there any way to get around this issue?

I know that a simple solution would be to create a constructor in A that takes an object of class B as its argument, or to create an operator in B that converts an object of class B to an object of class A. For my purposes, however, these solutions should not be used unless absolutely necessary.

I'm still learning C++ (I've come over from Java). Hopefully the code below will clarify what I'm talking about. Thank you for your feedback in advance.

#include <iostream>

// objects of class A can be (implicitly) constructed with an int
struct A {
    A(int) {}
};

// objects of class B can be (implicitly) converted to an int
struct B {
    B(int) {}
    operator int() { return 0; }
};

// myFunc takes an object of class A
void myFunc(A)
{ }

// why can't myFunc convert the argument b like the following: B -> int -> A?
int main()
{
    B b(5);

    // These work:
    myFunc((int) b);
    myFunc(A(b));

    // This does not:
    myFunc(b);
}

Note: The code above should compile properly until myFunc(b); is commented out.

Upvotes: 1

Views: 83

Answers (1)

MSalters
MSalters

Reputation: 179779

What you're looking for is called a conversion sequence in C++. To get from one type to another, there can be only a limited number of steps. Importantly, there can be at most one step from each of the possible categories. E.g. you can have at most one numeric promotion ( e.g. short to long.). Importantly for your example, there can be at most one user-defined conversion. This is either a converting constructor (Foo::Foo(Bar)) or a conversion function (Bar::operator Foo). Your example needs both.

Upvotes: 1

Related Questions