7

I came across a curious line of code of the form:

// Given the following definitions:
class B;
B b;

// Line of interest:
auto a(b);

I thought it must be a typo, but after some experimentation found out that it works, and seems to always call the copy constructor of the type of b (even if you have other classes that can also have a matching constructor, and even if you additionally delete the copy constructor for the type of b).

I don't know the technical name of such a statement, so I'm not sure how to search for it in cppreference or StackOverflow. How does the compiler parse this type of statement in general, and where is it documented?

--

Re: duplicate marking. I don't see how they've addressed this construct. I already know auto uses template type deduction, that doesn't clarify anything in this case.

Apollys supports Monica
  • 2,938
  • 1
  • 23
  • 33
  • 1
    Is that within a function or class or just in the global namespace? – Tas Sep 18 '19 at 01:37
  • 2
    C++'s grammar is not context-free. We can't tell you how this is parsed unless you tell us the definition of `b`. – Ben Voigt Sep 18 '19 at 01:41
  • *I thought it must be a typo* that is the working group name for the next C++, ahem, standard. – mevets Sep 18 '19 at 02:24
  • 1
    *additionally delete the copy constructor for the type of b* I don't think it means what you think it means. Create a [mcve]. – n. m. could be an AI Sep 18 '19 at 03:30
  • @BenVoigt You could still tell me how it's parsed, for example see the current answer's first couple sentences. I have simplified the question though. – Apollys supports Monica Sep 18 '19 at 20:07
  • "* I already know auto uses template type deduction, that doesn't clarify anything in this case.*" Why not? `auto` is a type specifier, which is deduced based on the way the variable it defines is initialized. I don't understand how your question is different. It's slightly more complicated, but it's ultimately the same question: how did it figure out what type to give `a`? Because once that's determined, all of the rest of your questions fall into place. Why does `B a(b);` copy the object? Because what else would that declaration do? – Nicol Bolas Sep 18 '19 at 20:09
  • Good question. But, if any of my guys did that, we'd have a long, uncomfortable chat. – 3Dave Sep 18 '19 at 20:10
  • If I tell you I want to construct an object given a single parameter `b`, how do you know or why do you assume I want to create an object of type equal to the type of `b`? (Where "you" = the compiler) @NicolBolas – Apollys supports Monica Sep 18 '19 at 20:11
  • @Apollys: Because you said `auto` and *that's how `auto` works*. As explained in the duplicate. – Nicol Bolas Sep 18 '19 at 20:15
  • @NicolBolas Why? Where is this stated? That's my whole question. – Apollys supports Monica Sep 18 '19 at 20:16
  • @Apollys: It's stated very clearly in the answers to the duplicate question. That's why your question is a duplicate. – Nicol Bolas Sep 18 '19 at 20:17
  • Please quote. I have read the answer and do not see it anywhere. – Apollys supports Monica Sep 18 '19 at 20:18
  • @NicolBolas please see ^ – Apollys supports Monica Sep 19 '19 at 18:50

1 Answers1

7

How is auto a(b); parsed in C++?

Depends on what b is. If b is a type, then this is a declaration of function with name a with deduced return type and a single argument of type b.

If b is not a type, then this defines a variable by the name a whose type is deduced from the initialiser.

where is it documented?

The authoritative documentation is the standard document. The standard sections [dcl.type.auto], [dcl.ambig.res], [dcl.fct], [dcl.init] should be relevant.

There are also websites that offer the documentation in (arguably) more approachable manner.

This should also be covered by recent (as in, anything since 2011) introductory C++ books.

and even if you additionally delete the copy constructor for the type of b

I doubt this. Create a mcve.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Responding to your last line. Of course I created an example before writing that. And of course when you call a deleted function you get a compiler error. But the line is **clearly, definitely** parsed as a call to the deleted copy constructor. – Apollys supports Monica Sep 18 '19 at 19:53
  • 1
    @Apollys oh, I see. I understood that you said that the function is *called*, which of course cannot happen if the program isn't running. Indeed, deleting the copy constrcutor doesn't mean that a copy initialization would mean something else. It just means that attempting to copy makes the program ill-formed. – eerorika Sep 18 '19 at 20:04
  • So then my question, and maybe I have to go to the standard to answer it: Why does it choose to try to call the deleted constructor for the type of `b` rather than select another constructor that could actually be valid? I assume that's to make things simpler, there must be a rule somewhere that says "this always tries to call the copy constructor of type of `b`". – Apollys supports Monica Sep 18 '19 at 20:06
  • @Apollys because the copy constructor is the most preferred one by the overload resolution. The rules that determine overload resolution are rather complex, but it should be intuitively reasonable that initializing an object from another of the same type would invoke the copy constructor. – eerorika Sep 18 '19 at 20:09
  • But why is it the same type? I might be missing something, but I feel everyone is using some form of circular logic. The key question is *Why is auto deduced to be `B`*? And everyone is answering that by assuming this line of code is creating a `B`. – Apollys supports Monica Sep 18 '19 at 20:14
  • `Why is auto deduced to be B?` In short: because that is the type of the expression used to initialize a. For long version, see the standard. – eerorika Sep 18 '19 at 20:15