On Tue, Dec 17, 2019 at 8:53 PM Jon Kalb <jon@kalbweb.com> wrote:

I am/was a AAA skeptic as well, and have been waiting for Concept x = ... (or now Concept auto x = ...) as the sweet-spot solution.

Now that we have:

auto x = expr;
Concept auto x = expr;

int x = expr;

fit the "pattern" better than

auto x = int{expr};

I think not. If I see this code:

int x = expr;

I’m not certain which of these is the author’s intent:
  • No matter what expr evaluates to, I want x to be an int.
  • This is legacy code from before auto existed.
That may be true, but does it change its intent?  "This is legacy code..." is not an option for "was this the author's intent". Is there 3 choices in this list or 2?
  • I’m guessing that expr returns an int   ...

OK, maybe.
  • ... and I’m not using auto out of programming style momentum.
Does that change the meaning, beyond the other points mentioned? Or is this part redundant?

But if I see this:

auto x{int{expr}};

I’m pretty certain that the meaning is, "No matter what expr evaluates to, I want x to be an int."

To be clear, you are suggesting that the "I'm guessing it returns an int" case would just be auto x = expr; yes?
Or would some people still write the int{expr} because they (sometimes) want to be clear about the type info? ie "I want the reader to know this is an int, since it wasn't actually very clear in context, and it is important in this particular case"

And, importantly, when the type of expr changes,are you sure that you still want it to be an int, with that conversion?
Now, int doesn't have explicit constructors so it is a bad example, but things like shared_ptr and chrono types do.
If you always write auto x = type{expr}, you lose the explicit/implicit distinction, thus losing a safety net that the committee thought was worth spending a keyword on.  In fact, most guidelines suggest explicit should be the default choice for constructors, yet this form of auto works against that guideline.

What is the value of

    auto x = int{expr};

This better conveys the intention that you really want x to be int without regard to the type of expr. The alternative “int x = expr;” just invites someone to notice that expr (either now or the future) might not be an int, and thus reflector it as “auto x{expr};

What about when I want it to be int regardless of the type of expr, unless that is an explicit conversion, because in that case I probably want to double-check.

Or what if I write auto x = type{expr} *precisely* because I want the explicit conversion?
Does that mean whenever I see auto x = type{expr} I'm left wondering "do they want the explicit conversion, or is this just their style for all occassions?"

You didn't comment on the examples which motivate my concerns:

Two real-life examples, from Howard Hinnant, paraphrased:

auto ns = nanoseconds{duration};  // duration was a chrono type, but became int, is this still what you wanted???
nanoseconds ns = duration; // if duration is strong chrono type, does the conversion you wanted/expected, if duration is int, fails to compile


auto sp = shared_ptr<Foo>(ptr);  // ptr is a weak_ptr, need shared
shared_ptr<Foo> sp = ptr;

When, under maintenance, ptr changes from weak_ptr to raw T* ptr, one of those lines is probably a bug, the other doesn't compile.
(And yes, maybe they should have called ptr.lock() on the weak ptr, but some people think that was a poorly named function (confusing with mutex etc) and prefer the conversion style.)

So I still prefer int x = expr; over auto x = int{expr};, and I think int x = expr nicely follows a pattern with auto x = expr and Concept auto x = expr.

Be seeing you,