Противоречивые возвращаемые типы итераторов std::set
Это вторая ошибка компилятора сегодня, которая запутала меня. Так или иначе для кода ниже, gcc жалуется, что в коде есть функция, которая возвращает итератор return_iter
возвращать конфликтующие типы std::_Rb_tree_iterator<const int*>
а потом std::_Rb_tree_const_iterator<const int*>
, но оба они не должны быть константными итераторами, потому что множество не является константным. Может ли кто-нибудь объяснить, почему std::end()
метод при вызове неконстантного lvalue возвращает const_iterator
?
Полный код вставлен ниже.
Обратите внимание, я получаю эту ошибку только при компиляции с gcc
, Эта ошибка не отображается при компиляции с помощью clang (Apple LLVM version 8.0.0 (clang-800.0.38)
, Я использую версию gcc g++ (GCC) 5.1.0
Смежный вопрос. Это правильное использование форварда? Считается ли нормально звонить std::forward
когда вы хотите использовать ссылку для пересылки? Причина, по которой я вызвал ее ниже, заключается в том, что тип перегружает некоторые методы, когда объект является значением.
#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;
}
LessPtr
как-то нужно вызвать эту ошибку..
1 ответ
Это ошибка libstdC++ в пути std::set
обрабатывает прозрачные компараторы. Вот более короткий пример:
int main() {
using S = std::set<const int*, LessPtr>;
S set_ptrs;
int i = 0;
const int ci = 0;
static_assert(std::is_same<
decltype(set_ptrs.lower_bound(&ci)), S::iterator>{}, "!"); // OK
static_assert(std::is_same<
decltype(set_ptrs.lower_bound(&i)), S::iterator>{}, "!"); // Error
return 0;
}
Первое утверждение в порядке, мы называем lower_bound(Key const&)
, который возвращает iterator
, Второе утверждение срабатывает, потому что мы вызываем шаблон функции template <class K> lower_bound(K const&)
, так как LessPtr
является прозрачным, и эта перегрузка является лучшим соответствием (потому что это точное соответствие), и эта, для libstdC++, возвращает const_iterator
,
Но set_ptrs
не const
так не должно быть. Я подал 78134