Personally, I have tended to use auto
for a select few types of code:
Unutterable types, such as those created by lambdas:
auto f = []() { /* some code */ };
iterators, since they all implement the same opaque interface. I don't care what specific type of iterator it is, just that it acts like one.
auto it = m.find(key);
if(it != m.end() {
/* some code */
}
if the type was already said on the same line, for example casts:
float f = 123.456;
/* some code */
auto n = static_cast<int>(f);
or similarly:
if(auto p = dynamic_cast<Derived *>(base_ptr)) {
/* some code here */
}
For everything else, I will tend to be explicit.
Regarding std::function
vs auto
, I will use auto
when I can, and then will fall back on std::function
as needed. This is because std::function
has a slight overhead since it is implemented using type-erasure techniques.
This usually means that I will use templates to implement functions which accept a "callable thing" when reasonable as well.
That being said, if I need to store a function, possibly pass it around, then std::function
is a great fit.