Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
226 views
Welcome To Ask or Share your Answers For Others

1 Answer

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 if statement is a selection statement, and it takes the grammatical form:

if (condition) statement

Here, condition can be either:

  • expression or
  • type-specifier-seq declarator = assignment-expression

And 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):

decl-specifier-seq declarator braced-init-list

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...