A before and after snippet on how to check if an STL container is empty.
The original code I recently saw was similar to this:
class MyClass
{
private:
std::vector<int> m_container;
public:
bool isEmpty()
{
if(m_container.size() == 0)
{
return true;
}
return false;
}
};
We want to focus on the isEmpty function. There is nothing wrong with is, but we can make it better and more expressive to the reader.
Express your intention
Always try to clearly express your intention in your code. If you check the documentation of std::vector you will see that it has a member called empty. Using this function instead of checking and comparing the container’s size() makes for better and more expressive code.
Step1 – Const correctness
Const correctness is a very important part in designing good interfaces.
As the isEmpty function does not change the logical state of the class it should be made const. For further explanation refer to the isocpp FAQ about logical vs physical const.
Step2 – noexcept
If you mark a function with noexcept and it throws an exception, std::terminate is called. Therefore be sure that when you mark a function with noexcept it will not throw.
If you check the documentation on std::vector::empty you will see that this is already noexcept (since C++11).
We can specify isEmpty as noexcept.
Improved version
An improved version that really just forwards the call can be written like this:
class MyClass
{
private:
std::vector<int> m_container;
public:
bool isEmpty() const noexcept
{
return m_container.empty();
}
};
This is it?
Well yes and you probably guessed it, if you are a little familiar with the STL.
Of course this example is fairly simple, as we only forward to an already existing member function that will do the job.
The purpose of this example was to demonstrate how to correctly use const and noexcept on your wrappers.
Because some cases might not be that easy to spot on first sight and analyzing them the way we did in terms of both const correctness and noexcept works the same.