The question is simple. Why does this compile:
bool b(true);
if (b) { /* */ }
And this compile:
if (bool b = true) { /* */ }
But not this:
if (bool b(true)) { /* */ }
In my real code, I need to construct an object and test it, while also having it destroyed when the if-block ends. Basically, I’m looking for something like this:
{
Dingus dingus(another_dingus);
if (dingus) {
// ...
}
}
Of course, this would work:
if (Dingus dingus = another_dingus) { /* */ }
But then I’m constructing a Dingus and calling operator= on it. It seems logical to me that I would be able to construct the object using whatever constructor I please.
But I’m baffled why this isn’t grammatically correct. I’ve tested with G++ and MSVC++ and they both complain about this construct, so I’m sure it’s part of the spec but I’m curious as to the reasoning for this and what non-ugly workarounds there may be.
It’s a bit technical. There’s no reason why what you want couldn’t be allowed, it just isn’t. It’s the grammar.
An
ifstatement is a selection statement, and it takes the grammatical form:Here,
conditioncan be either:expressionortype-specifier-seq declarator = assignment-expressionAnd there you have it. Allowing a declaration in a condition is a special case, and it must follow that form or your program is ill-formed. They could have probably allow direct-initialization instead of copy-initialization, but there isn’t really any motivation to do so now. As Johannes Schaub points out, this change would break existing code, so it’s pretty much never going to happen.
Let_Me_Be notes that C++11 added a third form (I’m ignoring attributes here):
So
if (bool b{true})is fine. (This can’t possibly break any valid existing code.)Note your question seems to do with efficiency: don’t worry. The compiler will elide the temporary value and just construct the left-hand side directly. This, however, requires your type be copyable (or movable in C++11).