jeudi 27 octobre 2016

Conflicting return types of std::set iterators

This is the second compiler error today that has gotten me confused. Somehow for the code below, gcc complains that the code has the function which returns an iterator return_iter return conflicting types std::_Rb_tree_iterator<const int*> and then std::_Rb_tree_const_iterator<const int*>, but both of them should not be const iterators because the set is not const. Could anyone explain why the std::end() method when called on a non const lvalue returns a const_iterator?

The complete code is pasted below.

Note I only get this error when compiling with gcc. This error does not show up when I compile this with clang (Apple LLVM version 8.0.0 (clang-800.0.38). The gcc version I am using is g++ (GCC) 5.1.0

A related question. Is this the correct use of forward? Is it considered ok to call std::forward whenever you want to use a forwarding reference? The reason I have it called below is just in case the type overloads some methods for when the object is an rvalue..


#include <vector>
#include <string>
#include <set>
#include <iostream>
using namespace std;

int global_value = 1;

class LessPtr {
public:

    template <typename PointerComparableOne, typename PointerComparableTwo>
    constexpr auto operator()(PointerComparableOne&& lhs,
                              PointerComparableTwo&& rhs) const {
        return *std::forward<PointerComparableOne>(lhs) <
            *std::forward<PointerComparableTwo>(rhs);
    }

    using is_transparent = std::less<void>::is_transparent;
};

template <typename Container, typename Key>
auto return_iter(Container&& container, Key&& key) {
    if (global_value == 1) {
        return std::forward<Container>(container).lower_bound(std::forward<Key>(key));
    }
    else {
        return std::end(std::forward<Container>(container));
    }
}

void do_stuff(std::set<const int*, LessPtr>& set_ptrs) {
    // auto value = string{"something"};
    auto value = 1;
    auto iter = return_iter(set_ptrs, &value);
    cout << reinterpret_cast<void*>(&iter) << endl;
}

int main() {
    std::set<const int*, LessPtr> set_ptrs;
    do_stuff(set_ptrs);

    return 0;
}

The LessPtr is somehow needed to cause this error..

Aucun commentaire:

Enregistrer un commentaire