Why can't variables defined in a conditional be constructed with arguments?

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.

Answers


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


Need Your Help

Does spring form taglib disabled attribute really have to resolve to a string?

java spring jsp spring-mvc

I've been playing around with the spring form taglib lately and came across a fairly disturbing phenomenon.

Making c++ app use directory of file, not pwd

c++ osx unix directory pwd

I am trying to run an application, app. I do this by running ./app in the directory of app. This application has a dependency, graphics/file.bmp. Everything works when I run ./app in that directory...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.