Hacker News new | ask | show | jobs
by rnallandigal 652 days ago
The std::to_chars function returns an object of type std::to_chars_result, which defines an operator bool() checking if ec == std::errc[0].

The if statement determines which branch to take based on the value of the condition. This value is contextually converted to a bool and evaluated[1].

[0] https://en.cppreference.com/w/cpp/utility/to_chars_result

[1] https://en.cppreference.com/w/cpp/language/if#Condition

1 comments

But there are two variables being defined by the destructuring. I believe OP's question was whether there's a rule for which gets chosen for the condition, rather than about contextual conversion to bool in general (which happens even when there's no initialisation in the if statement at all).

Your comment seems to imply the condition is evaluated before initialising the variable(s) at all; is that what you meant? If so, this beast would work (even though it's undefined behaviour to construct a std::string from nullptr, and std::string is not convertible to bool):

   const char* foo() // may return nullptr
   if (std::string s = foo())
Yes exactly. My hunch is to remember that in `auto [to, ec] = std::to_chars(p, last, 42)` the two names `to` and `ec` are not "real" variables/objects, but names bound to parts of the object returned to by `std::to_chars`. So fundamentally, `std::to_chars` returns a `std::to_chars_result`, that _is_ the return value and what is then contextually converted to bool for evaluation of the condition. It's then some C++17 compiler thing that separately associates the two names `to` and `ec` with the two parts of that returned tuple object.

But I could be wrong, the paper for the feature is linked but I didn't read it (!).

> Yes exactly.

Yes exactly, my example would work?

> My hunch is to remember that in `auto [to, ec] = std::to_chars(p, last, 42)` the two names `to` and `ec` are not "real" variables/objects, but ...

Oh so my example wouldn't work after all (because std::string s is a "real" variable/object)?

Your example wouldn't work, yes.

In case of structured binding

  The decision variable of the declaration is the invented variable e introduced by the declaration.
 
but in your case its simply:

  The decision variable of the declaration is the declared variable.
What is assigned (std::to_chars_result) is considered by the if condition. The left hand side of the assignment is then split in two. Just like if it were if (auto res = std::to_chars(p, last, 42)). The split with the [to, ec] makes it convenient inside the if body.
Ok but you've avoided saying whether my example would work, and I don't think what you've said even hints one way or another.
The result of the expression is the condition.

Thus, in your example, the bool check would apply to "s", after the expression is evaluated.

The fact that foo() may return nullptr at runtime and your "s" is UB is your fault for running with scissors.

so "this beast would work" for some definition of "work". But not because of order of evaluation.

Most modern C++ compilers would warn you about not using a bool in a conditional anyway.

> The result of the expression is the condition. Thus, in your example, the bool check would apply to "s", after the expression is evaluated.

This is a contradiction. There is no expression in my code that evaluates to s. foo() is an expression, and then std::string s = ... is assignment initialisation, which is not an expression.

Edit: I suppose that if I used another form of initialisation, the answer becomes a bit more obvious:

   if (std::string s('x', 3))
(Not that this makes sense but just the point is to use a constructor with more than one argument.) In this case it's clear the test has to be the just-initialised variable. In fact there could be no arguments at all!
You are using definitions that I am not familiar with. Maybe it's because we speak different programming languages :-)

x = y is an expression statement in C++, which can be evaluated in an "if" for its side-effects.

https://en.wikipedia.org/wiki/Expression_(computer_science)

But Type x = y isn’t.