0

Part of the answer is given in here

class foo1
{
private:
        int i;
public:
        foo1()  
        {
           i=2;
        }
        int geti(){
                return i;
        }
};

class foo2
{
private:
        int j;
public:
        explicit foo2(foo1& obj1) //This ctor doesn't have `const` intentionally as i wanted to understand the behavior.

        {
                cout<<"\nctor of foo2  invoked";
                j=obj1.geti();
        }
};

    foo1 obj1;
    foo2 obj2(obj1); //THIS WORKS

    foo2 obj22=obj1; //THIS DOESN'T WORK

Both of them work when the keywork explicit is removed.

Is the following explanation correct for copy initialization( foo2 obj22=obj1) :

At first the compiler creates a temporary object using constructor: foo2(foo1& other) {} then it tries to use this temporary object in the copy constructor: foo2(foo2& other) {} But it may not bind a temporary object with non-constant reference and it issues an error. When you are using the equal sign then there is used so-called copy-initialization.

If yes, then shouldn't foo2(foo1& other) {} itself be disallowed before even going further because temporary cannot be bound to non const reference?

Sorry for the long question, my confusion is basically around difference behavior for direct and copy initialization in presence/absence of explicit keyword(with/without const)

anurag86
  • 1,635
  • 1
  • 16
  • 31

1 Answers1

1

Is the following explanation correct for copy initialization

It isn't. You omitted the definition of a copy c'tor for foo2. Which means the compiler synthesizes one for you automatically. The synthesized version will take by a const foo2&. So the issue is not in binding a temporary foo2 to a non-const reference.

As a matter of fact, copy initialization no longer creates temporaries, and doesn't even have to behave as though a temporary is present. What instead happens is that the form of initialization simply takes the explicit keyword into account.

Both of these

foo2 obj2(obj1); 
foo2 obj22=obj1; 

perform the same overload resolution, which can only choose the same c'tor (foo2(foo1& obj1)). It should choose this c'tor because you pass a non-const lvalue for an argument.

The difference? Direct initialization is allowed to use an explicit c'tor. While copy initialization does not. So your explicit c'tor is not a candidate, and overload resolution fails.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • I think this part of the answer is the gist of what i'm looking for essentially _While copy initialization is deemed ill-formed when an explicit c'tor is chosen._ Can you shed some more light,references on – anurag86 Feb 02 '20 at 09:08
  • @anurag86 - See [here](https://timsong-cpp.github.io/cppwp/n4659/class.conv.ctor#1) and [here](https://timsong-cpp.github.io/cppwp/n4659/over.match.copy). I need to paraphrase a little. – StoryTeller - Unslander Monica Feb 02 '20 at 09:12