5 ms·
My 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);
by Asooka 9y ago
My 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.