Lin
Lin

Reputation: 355

Compile time validation for iterator usage?

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

Answers (1)

Nicol Bolas
Nicol Bolas

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

Related Questions