Auto in C++

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.

Leave a Reply

Your email address will not be published. Required fields are marked *