Learned that C++17 supports If statement with initializer. I think it’s useful when dealing with iterators in VTK.
There are instances of code in VTK that assign and check the value in the argument of if
to prevent accidentally dereferencing a null pointer and/or limiting the scope of a resource.
Example:
This is safer
if (auto gradients = pointData->GetArray("Gradients"))
{
// print gradients
auto r = vtk::DataArrayValueRange(gradients);
std::copy(r.begin(), r.end(), std::ostream_iterator<double>(std::cout, '\n'));
}
// gradients variable cannot be accessed anymore.
instead of writing
auto gradients = pointData->GetArray("Gradients");
if (gradients != nullptr)
{
// print gradients
auto r = vtk::DataArrayValueRange(gradients);
std::copy(r.begin(), r.end(), std::ostream_iterator<double>(std::cout, '\n'));
}
// gradients is nullptr, but the variable is still accessible!
As useful as that is, it’s not possible to do that with iterators. Right now, this, by itself, will fail to compile.
if (((auto iter = entries.find(key)) != entries.end))
{
std::cout << iter->first << ':' << iter->second << std::endl;
}
leading one to write unsafe code
auto iter = entries.find(key);
if (auto iter = entries.find(key))
{
std::cout << iter->first << ':' << iter->second << std::endl;
}
// compiler doesn't complain when iter is accidentally dereferenced, crashes at run time.
int a = iter->first;
With if-initialization statements in C++17, that can be re-written safely.
if (auto iter = entries.find(key); iter != entries.end())
{
std::cout << iter->first << ':' << iter->second << std::endl;
}
// iter is inaccessible. compiler will complain if iter is dereferenced.