12 ms·
Don’t use C++ auto? Restricting auto is not the best decision
- tzahola 9y agoHm. I thought using auto was the recommended, modern way of writing C++.
- ska 9y agoIt is. Some people don't want to learn how it works, and have been bitten by unexpected results. Like nearly everything in c++, there are some odd corner cases. However, auto is a big net win. You should understand it, and you should use it.
- ChrisSD 9y ago> However, auto is a big net win. You should understand it, and you should use it. Which is a fair summary of the linked article.
- Asooka 9y agoMy rule of thumb is "the type has to be stated clearly and unambiguously at least once on the line the variable is declared. Yes: auto foo = new Foo(bar); Maybe: auto foo = FooFactory::newFromBar(bar); No: auto foo = bar(baz);
- Sharlin 9y agoHowever, there are many situations where the actual name of the type is only known to the compiler, or is so complex that nobody in their right mind would type it.
- contravariant 9y agoThe only case I know of are lambda expressions. And for those I would argue that the type is obvious, but impossible to name.
- roel_v 9y agoIn template meta-programming, there are many cases where you don't know types until your template is instantiated; which, when you're writing libraries, could be with many types. Auto is a 'nice to have' when doing regular OO or generic programming in C++, but it changes (some) template meta programming from 'too difficult to bother with' to 'feasible'.
- contravariant 9y agoI can think of cases where the names get so complicated you really don't want to bother writing them out in full, but I'm having trouble coming up with a scenario where you'd end up with anonymous type through templates.
- Sharlin 9y agoThe type, albeit nameable, may not be a part of the public API—it could be an implementation detail subject to change. This is the case with some standard library types such as those returned by std::bind where the exact name of the type is explicitly left unspecified. It is possible to enforce this by returning a type whose name has private visibility—such a type is perfectly usable from the outside of its declaring class except that you cannot refer to it by its name.
- mattnewport 9y agoFunctions can return local types whose name is then not accessible to other code. Other code can use that type via auto though. As mentioned in another comment, not being able to name or even easily refer to a type without auto is very common in generic code.
- laurent123456 9y agoAlso, in my opinion, cases where the type is not relevant to the way the variable is used. For example: auto itemId = item->id(); // Could be an int, could be a string... processSomeItem(itemId);
- mhogomchungu 9y agoThere could be an efficiency bug here. 1. "item->id()" is designed to return a pointer. 2. Consumer of the API writes their code to take a copy of the pointer and passes it along to "processSomeItem". It is cheap to make a copy of a pointer 3. The API is changed and it now returns a reference. 4. The assignment to "itemId" now makes an expensive copy of the object behind the reference causing inefficiency bug. 5. "processSomeItem()" API can handle the copy and the code compiles and runs without the problem being noticed.
- ChrisSD 9y agoI'm not sure that it's safe to use an unstable API without being very careful and understanding the breaking changes before updating it.
- arximboldi 9y agoActually performance problems are way more probable when not using auto. Example: std::function<void()> = [] { ... }; Vs: auto = [] { ... } In the first case you are doing type erasure, which adds quite few penalties. Even in other cases, the type you typed might be convertible from the actual thing that is returned, causing extra conversions. If you always use "auto" the chances you use the right type and do less conversions is way higher.
- mhogomchungu 9y agosometimes,declaring lambdas with auto is not not sufficient as i discovered in my "tasks"[1] project. An example place where auto breaks is here[2]. [1] https://github.com/mhogomchungu/tasks https://github.com/mhogomchungu/tasks [2] https://github.com/mhogomchungu/tasks/blob/a1512a1b5e0392a069305a779e1e2834ca67d94d/task.h#L896-L916 https://github.com/mhogomchungu/tasks/blob/a1512a1b5e0392a06...
- nimish 9y agoThis is the general rule of thumb for `var` in C# that I've seen, which has similar issues to `auto` in C++. That said, there are awful compiler inferred types that C# doesn't have, so `auto` has a much wider application than `var` does.
- symlinkk 9y agoAny decent IDE should be able to tell you the type by hovering your mouse over the variable, even if it's made with auto.
- quickben 9y agoYeah, but that's corner case. We usually read code on screens, paper, email, git history, etc.
- roel_v 9y agoFor simple cases yes, but in the cases where you need auto the most (preprocessor or template meta programming) it very often doesn't work, and can't even work because it doesn't know the template types it's being instantiated with.
- robostac 9y agoThis means that using auto for iterators (which is one of the most useful uses in my experience) wouldn't be allowed.
- makecheck 9y agoNote that since smart pointers showed up about the same time as the revamped “auto”, you should use std::unique_ptr<>, etc. with “new” and not need “auto” there either.
- criddell 9y agoAnd make use of std::make_unique<>. auto foo = std::make_unique<Foo>(25.3, true);
- gcp 9y agoBut why? Duck typing works fine.
- kazagistar 9y agoAny reasoning for this rule? I don't code C++, but in the languages I do use with inference, I just use the maximum allowed inference within a function, and rely on simplicity and good naming to get by.
- Asooka 9y agoThe reasoning is to know what you're creating. Yes, iterators can probably also benefit from auto. But the concrete bug that prompted some introspection into what the rule should be was: void mutate(Foo &foo); ... for(auto foo : manyFoos) mutate(foo); If manyFoos is Foo[], then the auto type is Foo, rather than Foo& and you're mutating a copy. The goal is to not get screwed by the type inference, so unless you can defend why it's obvious that the type is what it is, don't use auto. An auto that you need to ask the IDE for it's concrete type is a strong code smell.
- mratzloff 9y agoI basically only use it for non-scalar variable assignments where the type is obvious, or iterating over collections. I never use it for function return types or parameters; that's just tedious to grok.
- Koshkin 9y agoThe worst part is, you have to be extremely careful here and make sure that you did not mean to write auto& foo = bar(baz);
- to3m 9y agoI go one step further - the interesting part of the type has to be mentioned in a form that you can click on and do a Go To Definition (etc.). So auto foo=FooFactory::newFromBar(bar) is no good, because you can't click on the exact type newFromBar is returning. But you might say auto thing=GenericFactory::Create<Thing>(), and that's OK, because you can click on the identifier Thing. (The point about the 'interesting' part is to permit stuff like std::unqiue_ptr<T> F<T>() and the like.)
- TheCoelacanth 9y agoThat rules out one of the core use cases that auto was designed for: iterators. std::unordered_map<SomeTemplatedType<A, B>, SomeOtherTemplatedType<C, D>> map = foo(); std::unordered_map<SomeTemplatedType<A, B>, SomeOtherTemplatedType<C, D>>::iterator it = map.begin(); is much less readable than std::unordered_map<SomeTemplatedType<A, B>, SomeOtherTemplatedType<C, D>> map = foo(); auto it = map.begin();
- ovao 9y agoIn the case of `auto foo = bar(baz);`, while specifying the type of the returned value may be useful in many cases, it would also require modification should the return type of `bar` change in the future. So the type specificity can come with a caveat.
- maxxxxx 9y agoAnd I thought auto was the best thing ever to happen to C++? Especially when working with STL.
- gambiting 9y agoMy problem with auto is that Visual Studio loses all ability to predict code when you use it. So when I do Type object and then do object. I get all the methods/members available for that Type. But if I use auto, VS is either can't recommend anything or recommends the wrong set of methods entirely. It really slows me down as a programmer and I hate using it for that reason.
- maxxxxx 9y agoThat seems to be a VS problem. They could easily infer the type and give you correct auto complete. It works perfectly fine in C# when you see var.
- deleted 9y ago[deleted]
- EpicEng 9y agoVS handles it just fine, this is something specific to the parent.
- stefantheard 9y agoDefinitely shouldn't be restricting how you code based on your IDE. If VS can't handle auto, either update for a fix or switch to CLion, it works just fine there.
- gambiting 9y agoIf the environments I code for only use VS(Xbox One/PS4) then I think it's fair to code for that IDE. We use Visual Assist at work and auto + hugely templated classes are a complete fail, it just gets no predictive text at all.
- Kenji 9y agoI never use auto in C++, except for when I have very complicated (or impossible to define) types like lambdas. I want complete clarity about what types I am using.
- dogruck 9y agoThe title is misleading. It starts with that argument as a preamble, but the bulk of the content is a detailed technical explanation for how “auto” works in C++. I was expecting some style guide rules of thumb. Scott Meyers does a good job of explaining “auto” in Effective Modern C++.
- mannykannot 9y agoRules of thumb work a lot better, and are often easier to explain and remember, if you understand their rationale.
- dogruck 9y agoI completely agree with you. I just think the linked article could be strengthened by adding some rules of thumb. No complaints about its technical explanation.
- mannykannot 9y agoI see what you mean - those rules don't help with writing code.
- bitL 9y ago'auto' makes it difficult to predict what type you actually need for a new method that uses some parameter you get from a 3rd party library. I once had like 12 nested templates revealed to me only during debugging with RTTI as a type of some innocent auto parameter.
- gcp 9y agoThis doesn't sound like a case where auto is the one making things harder...
- roel_v 9y ago"Effective Modern C++" (Scott Meyer) has a chapter on how to tease deduced types out of compilers. You can argue "it's silly that I even have to do that", and yes I'd argue that too, but sometimes you just need auto inside templates. Before I started using it, I thought it'd be a train wreck, but now I quite like it - when used judiciously. I do find myself writing code with auto, then when I revisit it at some point, replace it with the explicit type for readability. But that's only for a small percentage of the cases where I use auto, so overall it's a net plus.
- AnimalMuppet 9y ago> ... when used judiciously. That applies to many C++ features, not just auto. Maybe the problem with C++ is that it's not a language that you can use well without developing a sense of good taste - knowing when to use certain things, and when not to. (And then you have to interface with code written by someone else who didn't have any taste, and just used features without regard to whether they made things better or worse...)
- pjmlp 9y agoThat applies to any production language that has been in the wild for a few decades.
- roel_v 9y agoPff, is that a problem with C++ or with programming in general? There is not a single language in the world you can use well without developing a sense of good taste. And what is good taste not only differs between languages (for the exact same concept, like how do you sum the values of an array, or how do you execute two code paths in parallel), but also changes over time.
- raverbashing 9y agoThis shouldn't even be up to discussion. Auto is better overall Compilers know types better than humans. Whoever bans it (whithout a very, very compelling reason like "some of our code has to compile in an old compiler") is being a luddite at best. This should have been in C++ from its inception to be honest, to avoid blah_type<with_this> something = new blah_type<with_this>() repetition.
- pjmlp 9y ago> This should have been in C++ from its inception to be honest It was, but the backslash was even greater back then, so Bjarne removed it from C with Classes. There are a few presentations/interviews where he mentions it.
- cjensen 9y agoThat was an entirely different auto. In C89, auto just "variable on the stack". It still had a type. The new auto is just borrowing the keyword since it (a) makes sense and (b) is already a reserved word.
- pjmlp 9y agoHow the keyword was named when Bjarne introduced it doesn't matter, the purpose was the same as C++11 auto.
- Shorel 9y agoIt was entirely another concept. Before C++11 auto meant it was not static, extern or register, and in fact every single variable was already implicitly auto if no specifier from the previous list was applied. int n = 10; In that line, n was auto. Now it is not auto, only int.
- pjmlp 9y agoType inference is orthogonal to whatever keyword is used. Bjarne used another keyword in C with Classes, removed it due to backslash, and the commite decided to re-purpose auto for the same purpose in C++11. No big deal, the meaning of static is also context dependent, and no one is fighting against it like it happens with the new meaning for auto.
- Koshkin 9y ago'auto' is a terrible choice of the keyword. 'var', like in C#, would be much, much better. But no, the C/C++ people have been bitten by this weird keyword overload bug - the same one that caused 'static' to also mean "local"...
- nightcracker 9y agoThe issue is that 'var' would make old code not compile anymore, while 'auto' was already a keyword with pretty much no use.
- monocasa 9y agoExactly; 'auto' was the corollary of 'register'. Ie. it specified that the variable was to be put into automatic storage. On most architectures this means the stack. So not only did it specify what was the default behavior anyway, but it's better to let the compiler figure that out too.
- Koshkin 9y agoThe change of the meaning of 'auto' already broke the old code. In C, 'auto' is used to specify a storage class; in C++, it stands for the type. So, the valid C code auto float x; when compiled with a C++ compiler, produces an error message.
- beojan 9y agoIf we're talking about actual C++ code, auto is a reserved keyword (so it wouldn't be used as an identifier) but it was useless, so it wouldn't be used as a keyword in any real (C++) code.
- TheCoelacanth 9y agoThat was virtually never used in the wild, though.
- rootbear 9y agoThe real problem here is that keywords are in the same namespace as identifiers. If keywords were marked syntactically in some way and in their own namespace, there would be less reason to avoid introducing new ones. This is why we end up with _Bool, _Atomic, _Complex, etc., with hacky macro aliases. This is a problem in nearly all programming languages I'm familiar with.
- TACIXAT 9y agoAuto is nice to use, but I absolutely hate getting up to speed on a code base that uses it.
- mattnewport 9y agoThis suggests you need a better IDE.
- TACIXAT 9y agoYou are correct. I work in Sublime Text.
- gumby 9y agoFunny, I feel the opposite! I'm quite happy to ignore the type in most cases (especially in templates) when I see a line like auto dest = make_data_sink(....blah blah....); At that point I am unlikely to even worry about the type.
- Dylan16807 9y ago> At this point, you are probably thinking: “Holy cow! All these rules, and he is not even done with Use Case 1!” No, I'm thinking "Holy cow! He used so many words to explain such simple behavior!" The initializer list rule seems like a bad idea, at least.
- vanderZwan 9y agoSo this is a bit of a tangent, but Julia has this ability to use their typing system in such a way that lets you restrict what subtypes are allowed to be assigned to a variable (I'm just using Julia as an example because that is where I first saw this, I'm sure it originated from Scala or something; I'm not a CompSci historian). So if we have these abstract types: abstract type Number end abstract type Real <: Number end abstract type AbstractFloat <: Real end abstract type Integer <: Real end abstract type Signed <: Integer end abstract type Unsigned <: Integer end ... then I can make a function that takes any value as long as it's a subtype of Number, which implies I can do addition and subtraction and all the other things all numbers can do. So I still have the type safety of not ending up with an object where I want a number, but it is still extremely easy to write generics in Julia[0]. Can you do something like that in C++? So like: auto <: SomeBaseClass Meaning auto would work just like it normally does, except that if you assign something that is not derived from SomeBaseClass the compiler complains, giving you some extra safety checks when composing code with auto all over the place. [0] https://docs.julialang.org/en/stable/manual/types/ https://docs.julialang.org/en/stable/manual/types/
- mattnewport 9y agoConcepts give you something like this for template parameters, so instead of saying template<typename T> you can say template<Numeric T> where this would constrain the template to only be instantiable with type satisfying the Numeric concept. There's also some syntactic sugar where you can just say auto f(Numeric x) and this means template<Numeric T> auto f(T x). Concepts are in the process of standardization and are expected to be part of C++20. This is nothing to do with inheritance though in C++. Concepts are type constraints and don't require any particular inheritance hierarchy which is a much better way to handle things than using inheritance for this purpose.
- vanderZwan 9y agoThanks for the explanation! I vaguely remember reading about concepts and didn't quite get how they would be used in practice, but this seems like a good example.
- 9y ago
- jwilk 9y agoWhat a terrible title. My poor monkey brain couldn't cope with the amount of negation, and thought it's a criticism of "auto".
- jkforpres 9y agoIf you're still using c++ in 2017, you're already doomed. While I understand not everyone is pro enough to translate old rotting code to Rust and other superior languages, you still can make your contribution to humanity by writing new projects in better languages. For how many upcoming years will you fool yourself writing in shitty languages and calling yourself programmers while inflicting pain upon next generation of programmers lol.
- bostonpete 9y agouser: jkforpres created: 17 minutes ago Didn't even want to use your normal account? Way to stand behind your inflammatory comments.
- jkforpres 9y agoThe truth is always bitter my friend. You could've made an argument against my cases but instead you chose to derail the discussion lol.
- erikbye 9y agoYes, because C++ isn't good enough to handle complex projects that require performance AND safety, few bugs. Like the whole F-35 platform. Hardly old and rotting. If you know what you're doing you can write safe and performant code using this language. I'll let you know though, it's a trick not that many people know how to perform, and it's not a fault of the language, but bias and misconception. But sure, for the next JSF program, let's just try something new and immature. It's weird how people can't fathom that we're not all using their favorite language for real-time, safety-critical systems. Don't you think it's with good reason? That, in billion-dollar projects, all options have been considered? Everyone is using C and C++ for this purpose. From BAE to JPL.
- pjmlp 9y agoLarge scale projects aren't always about technology. Hiring process, politics and developer salaries also play a big role.
- millstone 9y agoauto can be ambiguous: template<typename Collection> void foo(const Collection &c) { auto x = c.find("foo"); ... } is x an iterator (Collection is std::map) or a number (Collection is std::string)? Here it is better to write out the iterator type if that's what you mean. auto can also be downright misleading: template<typename T> void foo(std::vector<T> &c) { auto first = c[0]; ... } `first` has type T except when T is bool. Gross. Better to write out the type T. auto can simplify many cases, but please don't take Sutter's "almost always auto" suggestion. Keep your future code readers in mind and be aware of its pitfalls.
- smitherfield 9y ago> is x an iterator (Collection is std::map) or a number (Collection is std::string)? Here it is better to write out the iterator type if that's what you mean. The reader would be able to infer this from context (as is the compiler, so it's still type-safe). > `first` has type T except when T is bool. Gross. Better to write out the type T. That's a preexisting problem with `vector<bool>` much more than it is with `auto`.