0

tl;dr: What is the hindrance to declaring an auto array?

I'm a very sparse auto user (basically with the exception of iterators where it's really helpful only using it when left absolutely no other choice, such as with lambdas), so I never realized this before. Almost Always use Auto? Pffft.

Today I was initializing an array of SSE constants (which is annoying enough thanks to Intel intrinsics). Doing so, it occurred to me that actually auto reads much nicer than __m128i and is much easier to type, too. And seeing how it's absolutely certain what the _mm_set... functions return, it should be trivially deducable, too. No risk of getting some undesirable promotion stuff either, looks like the perfect thing to do. Just works (TM).

Thus I went to write:

const auto foo[] = { _mm_set_blahblah(...),  _mm_set_blahblah(...),  _mm_set_blahblah(...) };

... only to learn that the compiler doesn't accept that!

After wondering whether it could be the const for a second (the error message being about "array of const auto"), I concluded it must be the Intel intrinsics, which are usually the source of all troubles, so why not this time. Also, you are perfectly allowed to write auto& and I'm sure that I've written auto const& at some point in the past. That really can't be it.

Surely, with everything else, it will work! But surprise, turns out it doesn't work with simple integers, either:

int  x[]  = {1,2,3}; // certainly works, what else!
auto y[]  = {1,2,3}; // no good
auto z[3] = {1,2,3}; // no good

Looking over at cppreference (easier than digging through the standard), it says: "may appear in the type specifier of a variable: auto x = expr;. The type is deduced from the initializer."

OK, alright, there's admittedly no square brackets in that statement, and it admittedly doesn't explicitly say "array" anywhere, but... an array is a variable (and it doesn't say "except arrays"), and there sure is an initializer.
An array is a bit special insofar as it's an aggregate, granted, but the same is true for many struct or class variables, and you are good to go with these.

The elements of an array must all have the same type, so there shouldn't be an issue deducing the element type correctly (other than maybe the fact that std::initializer_list uses the same syntax as aggregate initialization, but this isn't a problem elsewhere?). The size of the array is known from the initializer list as well, so that too couldn't really be much of a hindrance (also, the standard even requires this to work, plus, it doesn't compile with an explict size, either).

So, what is the reason why declaring an auto array isn't allowable?

Damon
  • 67,688
  • 20
  • 135
  • 185
  • _"An array is a bit special insofar as it's an aggregate, granted, but the same is true for many struct or class variables, and you are good to go with these."_ Really? Can you give an example of an instantiation of some object of class type, where the class type is deduced from constructor arguments? – Lightness Races in Orbit Dec 18 '19 at 17:51
  • Try `auto x = {1,2,3};` – John Dec 18 '19 at 17:51
  • _"The elements of an array must all have the same type, so there shouldn't be an issue deducing the element type correctly"_ All the arguments must convert to the same type; not the same thing. What if they convert to multiple things? – Lightness Races in Orbit Dec 18 '19 at 17:52
  • @John That is not an array. – Lightness Races in Orbit Dec 18 '19 at 17:52
  • Related: https://stackoverflow.com/q/16949016/560648 – Lightness Races in Orbit Dec 18 '19 at 17:53
  • 1
    This is just one more reason to stop using raw arrays and start using `std::array`. Now that C++17 has CTAD and C++20 will allow it to work through type aliases it's basically a drop in replacement. – NathanOliver Dec 18 '19 at 17:53
  • @LightnessRaceswithMonica: Well, a lambda _is_ a class of sorts, is it not? Not in a user-visible way, but under the hood, anyway. And you are surely allowed to use `auto` on it (what else could you do, not knowing its type). – Damon Dec 18 '19 at 17:54
  • That's not really the same thing. A lambda expression gives you an object already made. The `auto` in `auto f = [](){}` doesn't have any work to do; that's just a copy-initialisation. There is nothing to deduce. Similarly you can write `auto obj = GimmeObj()` but that's not a fair comparison to your array case either! – Lightness Races in Orbit Dec 18 '19 at 17:56
  • I'm not sure I agree with closing this as a duplicate. Knowing how to work around a problem is not the same as knowing how the problem came to be in the first place. – Mark Ransom Dec 18 '19 at 18:25

0 Answers0