Search code examples
c++iterator

c++ : warning comparing iterators


I have the following function to merge output for 2 containers :

template <typename IteratorType1, typename IteratorType2>

void Merge(IteratorType1 src1_begin, IteratorType1 src1_end,
           IteratorType2 src2_begin, IteratorType2 src2_end,
           ostream& out) {
    size_t i1 = 0, i2 = 0;
    size_t src1_size = std::distance(src1_begin, src1_end);
    size_t src2_size = std::distance(src2_begin, src2_end);

    while (i1 < src1_size && i2 < src2_size) {
        if (*src1_begin <= *src2_begin) {
            out << *src1_begin << std::endl;
            src1_begin++;
            i1++;
        } else {
            out << *src2_begin << std::endl;
            src2_begin++;
            i2++;
        }
    }
    while (i1 < src1_size) {
        out << *src1_begin << std::endl;
        src1_begin++;
        i1++;
    }
    while (i2 < src2_size) {
        out << *src2_begin << std::endl;
        src2_begin++;
        i2++;
    }
}

The problem is that I get a warning message at line ("comparison of integers of different signs") :

if (*src1_begin <= *src2_begin) {

Here is a use case :

template <typename T, typename S>
void MergeSomething(const list<T>& src1, const vector<S>& src2, ostream& out) {
    Merge(src1.cbegin(), src1.cend(), src2.cbegin(), src2.cend(), out);
}

int main()
{
    vector<int> v2{65, 75, 85, 95};
    set<unsigned> my_set{20u, 77u, 81u};

    cout << "Merging set and vector:"sv << endl;
    MergeSomething(my_set, v2, cout);
}

Is there any solution for it?

How can I silence the warning, given that I am certain that the comparison is actually ok?


Solution

  • If you're sure that both containers contain values in the same range you can cast the values to the same type. Following code removes the warning:

    #include <climits>
    #include <iostream>
    #include <list>
    #include <vector>
    using namespace std::literals;
    
    template <typename IteratorType1, typename IteratorType2>
    void Merge(IteratorType1 src1_begin, IteratorType1 src1_end,
               IteratorType2 src2_begin, IteratorType2 src2_end,
               std::ostream& out) {
        auto src1_size = std::distance(src1_begin, src1_end);
        auto src2_size = std::distance(src2_begin, src2_end);
        decltype(src1_size) i1 = 0, i2 = 0;
    
        while (i1 < src1_size && i2 < src2_size) {
            if (static_cast<decltype(*src2_begin)>(*src1_begin) <= *src2_begin) {
                out << *src1_begin << std::endl;
                src1_begin++;
                i1++;
            } else {
                out << *src2_begin << std::endl;
                src2_begin++;
                i2++;
            }
        }
        while (i1 < src1_size) {
            out << *src1_begin << std::endl;
            src1_begin++;
            i1++;
        }
        while (i2 < src2_size) {
            out << *src2_begin << std::endl;
            src2_begin++;
            i2++;
        }
    }
    
    template <typename T, typename S>
    void MergeSomething(const std::list<T>& src1, const std::vector<S>& src2, std::ostream& out) {
        Merge(src1.cbegin(), src1.cend(), src2.cbegin(), src2.cend(), out);
    }
    
    int main()
    {
        std::vector<int> v2{65, 75, 85, 95};
        std::list<unsigned> my_set{20u, 77u, 81u};
    
        std::cout << "Merging set and vector:"sv << std::endl;
        MergeSomething(my_set, v2, std::cout);
    }
    

    On Godbolt you can see that the compiler produces almost the same output.