Reputation: 355
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.
Upvotes: 1
Views: 177
Reputation: 473537
C++ is not a mind-reading language. All it knows are types. It knows that erase
takes an iterator. And it knows that i
is an iterator of the same type. Therefore, as far as the compiler's rules of C++ are concerned, it is legal to call erase(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 i
are not appropriate for this particular use of erase
. Your best bet is to just try to avoid mistakes. Range-based for
(or the use of std::for_each
) would help you here, as both of these hide the iterator.
Upvotes: 2