-3

I tried the following

auto ns=ms.capture[0].init,nl=ms.capture[0].len;

because I was too lazy to lookup what the types of the init and len fields were. The compiler didn't like it of course.

My understanding is that:

ttt xx,yy; 

is equivalent to

ttt xx;ttt yy;

So should the same work for auto? That is, shouldn't

auto xx, yy;

Become:

auto xx, auto yy;

Or there is something I don't understand in detail? Or is there something wrong with my compiler?

AndyG
  • 39,700
  • 8
  • 109
  • 143
George Kourtis
  • 2,381
  • 3
  • 18
  • 28
  • Better read about `auto` [here[(https://en.cppreference.com/w/cpp/language/auto). – Tanveer Badar May 03 '21 at 11:01
  • 2
    `auto` is not magic (well it is but not as much as you wish). You can think of `auto` like a placeholder for the actual type that is replaced by the compiler. Its not possible to replace `auto` in your code with the "correct" type – 463035818_is_not_an_ai May 03 '21 at 11:01
  • Does this answer your question? [C++11 "auto" semantics](https://stackoverflow.com/questions/8542873/c11-auto-semantics) – Tanveer Badar May 03 '21 at 11:01
  • You can get detailed information from this link. https://stackoverflow.com/questions/7576953 – east1000 May 03 '21 at 11:03
  • *Or there is something I don't understand in detail?* Yes. – Eljay May 03 '21 at 11:03
  • 5
    btw, maybe you would collect less downvotes if you summarized what you found in documentation and what makes you believe that your code should work. Currently the question reads like "I want it to work like that but it does not." – 463035818_is_not_an_ai May 03 '21 at 11:04

2 Answers2

6

auto is a placeholder for type deduction. In your case here, it is deduced from the initializer.

As you said:

T1 a, b;

is equivalent to:

T1 a; T1 b; // (A)

but not equivalent to:

T1 a; T2 b; // (B)

Hence, when you write:

auto ns=ms.capture[0].init,nl=ms.capture[0].len;

The compiler struggles to determine the underlying type because the init member is a const char * and the len member is an int (according to your error message). You gave two initializers with different types. We are in the case (B) of the above examples.
Consequently, the type deduction fails.

To make it simple, your code would be valid if it is possible to replace the auto specifier with an actual type (which isn't the case here).

Fareanor
  • 5,900
  • 2
  • 11
  • 37
3

As you said, (and Fareanor said)

ttt xx,yy; 

is equivalent to

ttt xx;ttt yy;

So it's not possible for

auto xx,yy = ...;

to deduce

char* xx, int yy = ...;

auto in the way you wrote it is only able to infer one type. What you are looking for is "tuple initialization". I say it like that within quotes because it's not a real thing, but there's a common pattern in C++ and other languages that looks like what you're doing.

For example, in Python:

xx, yy = "foo", 42

Will indeed initialize xx and yy as you'd expect.

In C++ pre-C++17 you could kind of achieve this via tuple assignment:

char* xx;
int yy;
std::bind(xx, yy) = std::make_tuple("foo", 42);

(And C# works pretty much the same way). It's not great; you are forced to declare your types, then wrap references to them in a tuple via bind, and finally perform assignment. Meaning you don't get to take advantage of copy elision, and your types either need to be default-constructible or else you call a constructor with meaningless parameters.

However, post C++17 we can use Structured Bindings where we can get type inference, copy elision, and all that good stuff.

Now we can say:

auto [xx, yy] = // array/tuple-like/POD-type

And we will get appropriate types for xx and yy. Here's an example approximating the code you posted:

struct Member{
    const char* init = "foo";
    int len = 42;
};

struct Test{
    std::vector<Member> capture{Member{}};
};

int main()
{
    Test ms;
    auto [ns, nl] = ms.capture[0];
}

Live Demo

AndyG
  • 39,700
  • 8
  • 109
  • 143