Summary
In this post, I will introduce auto
and decltype
in C++ 11.
Why Auto
In some situations, auto
makes codes more readable. It will tell the compiler to deduce the type of a declared variable from the initialization expression. The details are complex. At present, we want to make codes correct, clean, and simple.
As it is said, keep things consistent in your codes.
Good Situations
The following situations are good to use auto
.
Before make_xxx
It is very clear for reviewers that what type the variable should have when calling make_xxx
.
//without auto. Not that good, looks cumbersome
SomeType<OtherType>::SomeOtherType * obj1 = new SomeType<OtherType>::SomeOtherType();
std::shared_ptr<XyzType> obj2 = std::make_shared<XyzType>(args...);
std::unique_ptr<XyzType> obj2 = std::make_unique<XyzType>(args...);
//With auto. good : auto increases readability here
auto obj1 = new SomeType<OtherType>::SomeOtherType();
auto obj2 = std::make_shared<XyzType>(args...);
auto obj3 = std::make_unique<XyzType>(args...);
Iterator-based Loop or For-Each Loop
It is a good idea to use auto
in iterator-based loop or for-each loop.
//without auto.
for (std::map<std::wstring, std::map<std::wstring, int>>::iterator outerMap_Iter = StudentGrades.begin(); outerMap_Iter != StudentGrades.end(); ++outerMap_Iter)
{
//Print out the student name
std::wcout << outerMap_Iter->first << std::endl;
for (std::map<std::wstring, int>::iterator innerMap_Iter = outerMap_Iter->second.begin(); innerMap_Iter != outerMap_Iter->second.end(); ++innerMap_Iter)
{
//Print the grades here
std::wcout << innerMap_Iter->first << " : " << innerMap_Iter->second << std::endl;
}
std::wcout << std::endl;
}
//With auto.
for (auto outerMap_Iter = StudentGrades.begin(); outerMap_Iter != StudentGrades.end(); ++outerMap_Iter)
{
//Print out the student name
std::wcout << outerMap_Iter->first << std::endl;
for (auto innerMap_Iter = outerMap_Iter->second.begin(); innerMap_Iter != outerMap_Iter->second.end(); ++innerMap_Iter)
{
//Print the grades here
std::wcout << innerMap_Iter->first << " : " << innerMap_Iter->second << std::endl;
}
std::wcout << std::endl;
}
// Best
for (auto const &outer_iter : StudentGrades)
{
std::wcout << outer_iter.first << std::endl;
for (auto const &inner_iter : outer_iter.second)
{
std::wcout << inner_iter.first << " : " << inner_iter.second << std::endl;
}
}
I will introduce the difference of auto const
, auto &
, etc in future posts.
Lambda Functions
Lambda functions are good when you need anonymous functions. I will introduce Lambda function in future posts.
// Use function object
std::function<int(int, int)> func_multiply2 = [](int a, int b) -> int { return a * b; };
std::cout << func_multiply2(2, 3) << std::endl;
// Use auto
auto func_multiply = [](int a, int b) -> int { return a * b; };
Bad Situations
Intercept the value of functions
It is very confusing to get a value without readable type which means you may need to go to another file to search the definitions.
// confusing
auto a = ConjureMagic();
SetMagic(a);
Method Arguments
It will take considerable codes to catch all the exceptions.