I have the following piece of careless C++ code, which compiles without a hitch under VC10, but fails miserably during runtime. I am wondering if there is a way to validate this kind of error at compile time?
#include "stdafx.h"
#include <set>
void minus(std::set<int>& lhs, const std::set<int>& rhs)
{
for ( auto i = rhs.cbegin(); i != rhs.cend(); ++i )
{
lhs.erase(i); // !!! while I meant "*i" !!!
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int v_lhs[] = {0,1,2,3,4,5};
std::set<int> s_lhs(&v_lhs[0], &v_lhs[sizeof(v_lhs) / sizeof(int)]);
int v_rhs[] = {1,3,5};
std::set<int> s_rhs(&v_rhs[0], &v_rhs[sizeof(v_rhs) / sizeof(int)]);
minus(s_lhs, s_rhs);
return 0;
}
Note that I am fully aware that C++11 (as partially adopted early by VC10) has corrected the behavior that ‘erase” actually takes “const_iterator”.
Thanks in advance for any valuable inputs.
C++ is not a mind-reading language. All it knows are types. It knows that
erasetakes an iterator. And it knows thatiis an iterator of the same type. Therefore, as far as the compiler’s rules of C++ are concerned, it is legal to callerase(i).There’s no way for the compiler to know what you meant to do. Nor is there a way for the compiler to know that the contents of
iare not appropriate for this particular use oferase. Your best bet is to just try to avoid mistakes. Range-basedfor(or the use ofstd::for_each) would help you here, as both of these hide the iterator.