Adam Sikora
Adam Sikora

Reputation: 117

Weird constructor call

I have a class which does all its work in the constructor (it is constructed there, runs some calculacions, outputs them, and then it is destructed all this in constructor).

here is simplified code:

#include <iostream>

class myInt {
public:
    myInt(int init) : mInt(init) {}

    int mInt;
};

class SinglePara {
public:
    SinglePara(myInt first) : member(first.mInt) { std::cout << member << std::endl; this->~SinglePara(); }

    int member;
};

class TwoPara {
public:
    TwoPara(myInt first, myInt second) : member1(first.mInt), member2(second.mInt) { std::cout << member1 + member2 << std::endl; this->~TwoPara(); }

    int member1, member2;
};

int main()
{
    myInt one(1), two(2), three(3);
    TwoPara myTwo(one, two);      // outputs 3 as expected
    TwoPara(one, two);            // outputs 3 as expected

    SinglePara mySingle(three);   // outputs 3 as expected
    SinglePara(three);            // won´t compile

    std::cin.ignore();
    return 0;
}

Now the first 3 examples in my code behave exactly in the way I would expect them to. But the last one won´t even compile because it thinks I want to call copy constructor even though three is myInt. When SinglePara and TwoPara take as arguments integers instead of myInt then all four examples behave as I want them to.

Can someone explain this behaviour and tell me how to fix the fourth example if possible?

I´m using MSVC 2013

Upvotes: 1

Views: 100

Answers (1)

AnT stands with Russia
AnT stands with Russia

Reputation: 320401

Your

SinglePara(three);

is equivalent to

SinglePara three;

It is just a declaration for object three with a pair of redundant () around the name. But you already have an object named three declared before. You cannot declare another one in the same scope. Hence the error.

You apparently wanted your SinglePara(three) to be an expression that creates a temporary object of type SinglePara. Typically it happens "by itself" when you use in a context that unambiguously indicates that it is an expression. In your case you used it without context, creating the "expression vs. declaration" ambiguity, which always gets resolved in favor of declaration.

If you really just want to create a short-lived temporary, something expression-specific will help to push the compiler in proper direction. For example, a fictive use of comma operator will make it unambiguously an expression

SinglePara((0, three)); // OK
0, SinglePara(three); // OK

As a solution this is rather inelegant, but it does illustrate the nature of the problem. For a better solution, as it has been suggested in the comments, you can add a pair of parentheses

(SinglePara(three));

the make the compiler to recognize it as an expression.

Upvotes: 6

Related Questions