Video Coming Soon...
25: Auto keyword
I have to apologize. I've been making you write code like this:
std::vector<int> row = parse_line(line);
When you could have written this instead:
auto row = parse_line(line);
The auto keyword tells the compiler to figure out what type a variable should be based on how you're using it. If you use it for a return value, then it'll look at the function and give your variable the same return type as the function. You can even use it like this:
auto some_fancy_func(auto a, auto b) {
return a + b;
}
Doing this creates a function that can handle different types of parameters. Behind the scenes this is very complicated, but for now just know you can probably put an auto in places where you would put a type and C++ will figure it out.
You can also use auto& to create an automatically typed reference. This is a bit of a footgun though since it depends on what's being returned from a function, but in a for-loop it's a good option.
The Code
To practice auto take the code from Version 1 of Exercise 20 (name ex20_v2.cpp) and use auto everywhere that you can. I have my solution here where I only use it for a few return values, but see what you can get away with in your version.
See how I did it.
View Source file ex25_auto.cpp Only#include <fmt/core.h>
#include <fstream>
#include <vector>
using std::vector, std::string, std::ifstream, std::ios;
using fmt::println, fmt::print;
int chunk_number(const string& line, size_t start, size_t end) {
string chunk = line.substr(start, end - start);
return stoi(chunk);
}
vector<int> parse_line(const string& line) {
vector<int> result;
size_t start = 0;
size_t end = line.find(",", start);
while(end != string::npos) {
auto as_number = chunk_number(line, start, end);
result.push_back(as_number);
start = end + 1;
end = line.find(",", start);
}
// need to get the final chunk
auto as_number = chunk_number(line, start, end);
result.push_back(as_number);
return result;
}
int main(int argc, char* argv[]) {
string filename{argv[1]};
ifstream in_file(filename, std::ios::binary);
vector<vector<int>> table;
if(!in_file.is_open()) {
println("failed to open {}", filename);
return 1;
}
string line;
while(in_file) {
getline(in_file, line);
if(line == "") break;
auto row = parse_line(line);
table.push_back(row);
}
for(auto& row : table) {
for(auto cell : row) {
print("{}\t", cell);
}
print("\n");
}
}
When to Use auto
You should use auto when it's not necessary to know the return type of a function, or if you want to make a function that is generic and can take different argument types. Personally I rarely use it as a function parameter unless I'm using something called a "lambda" which we'll cover later.
Why to Use auto
The primary reason to use auto is not really to save on typing, but to make it easier to change your code later. It does save you on typing some terrible types you find in C++ but what it really does is this:
- Let's say in your game from Exercise 24 you wanted to change the name of your
enum class RoomIDtoenum class RoomIndex. - Since you didn't use
autoyou'll have to change that name everywhere you used it. You can use some IDEs to help do this automatically, but you'd still have to confirm the IDE got everything right. - If you use
autoinstead ofRoomIDthen you just change the name of yourenum classand you're done. C++ does it for you. - You can also change to other types that have similar behavior and as long as you use them the same it'll generally keep working.
Usually to get the full benefit of auto you need a nice automated test suite that makes sure your code keeps working with the new changes, but then you should always have that anyway. If you have some good tests, simple code, and simple data types, then auto will make it easier to work with your code and evolve it over time.
Why NOT to Use auto
Some C++ programmers love typing a lot of code. It makes them feel safe and warm to see mountains of <> and type names all over. If you ever work with them then you're stuck and can't use auto.
I find that auto also isn't helpful when used this way:
auto some_func() -> int {
}
This is stupid because you can just write this:
int some_func() {
}
There's no difference, but the first one seems to be some weird "Hey I'm a teen just like you kids" thing C++ programmers are doing today. I guess they think it looks like Rust or Go. I don't know why but it's stupid and mostly a dumb fashion thing they're doing to seem hip for no reason.
Further Study
Feel free to go back in time and use auto in your previous code. Definitely try to do it with your game to see if it helps.
Register for Learn C++ the Hard Way
Register to gain access to additional videos which demonstrate each exercise. Videos are priced to cover the cost of hosting.