I have always thought that auto
in C++17 is a placeholder for the actual data type, but it appears not so in the following:
tuple<int, int> permute(int a, int b){return {b,a};}
int main(){
auto [x,y] = permute(2,5);
cout<<x<<","<<y<<endl;
tuple<int, int> {x,y} = permute(2,5);
cout<<x<<","<<y<<endl;
return 0;
}
Why auto
requires [ , ]
while a tuple requires curly brackets?
EDIT: As pointed out below [ , ]
is C++17 Structured binding declaration. Nonetheless, my question remains: why can't I replace tuple<int, int> {x,y}
with auto {x,y}
?
Best Answer
auto [/*...*/]
is a completely different syntax construct from other declarations. (And it is supported only since C++17 btw.)It is a so-called structured binding, not a simple declaration of a variable. The
auto
keyword and brackets are part of that special syntax. They are not (directly) the type of a variable that is being declared or the initializer for such a variable.The
auto
is used in the behavior of a structured binding declaration to provide the declaration of an (unnamed) variable that is initialized from the right-hand side as if byin your example and
auto
will be deduced tostd::tuple<int,int>
.x
andy
then behave like references to the first and second element of this_unnamed
variable.The structured binding does not inherently have any connection with
std::tuple
. Any array type, aggregate type or type that provides a certainstd::tuple_element
/std::get
interface can be used with structured bindings.As for why specifying the explicit type directly instead of
auto
in this form of declaration isn't allowed, the only reason given in the proposal in section 3.6 is that one can always explicitly specify the type on the right-hand side if desired:I do not think there is any other reason that it hasn't been allowed. This seems a bit like simply personal preference of the proposal authors.
In
tuple<int, int> {x,y}
the braces are the initializer of an object, namely a temporary object of typetuple<int, int>
being created in that expression.Note that this is not a declaration at all. It uses the
x
andy
from the previous structured binding declaration to initialize the temporary object. It doens't declarex
ory
. You then assign to this temporary object the result ofpermute
which effectively doesn't do anything, because that object is immediately destroyed again at the end of the expresison.A simple declaration would look like this:
and this wouldn't allow accessing the elements by own names directly. You would have to introduce names for them as references specifically if you don't use the structured binding syntax:
tuple
is not in any way a special type in C++. Just because you use braces has no implication that you want to form a tuple. You can writeS{x,y}
for any suitable aggregate typeS
and it would be weird if the language preferredtuple
over other possible types.In many other languages a tuple type is not only a library type like in C++, but is instead more fundamentally connected to the core language. In this case the language will usually provide special syntax to form tuples, e.g. as
(x, y)
. In C++ tuples are not built-in types, have no special meaning in the core language and there is no syntax dedicated to them.You can however write
tuple{x,y}
. The element types can be deduced via CTAD (class template argument deduction) since C++17.That being said, there is indeed a special type in the standard library that is preferred whenever braces are used (and one can argue about whether it was a good decision to design it like that). This preferred type is however not
std::tuple
, but insteadstd::initializer_list
, which is a magic type that behaves similar to a copyable reference to an implicitly-created array, i.e. it works only with homogeneous element types and doesn't provide value semantics when being copied.So for example in
the type of
a
will be deduced tostd::initializer_list<int>
. This is meant to be used primarily for iteration in range-for loops and for passing to constructors of containers. So even if preferring one type over the other wasn't weird anyway, C++ already made a choice for another type other than tuple.