Я хотел бы создать контейнер с данными, который включает в себя итератор самого контейнера.Упрощенный код ниже.Он работает для большинства контейнеров STL (vector
, set
и т. Д.), Но не компилируется для unordered_set
с некоторыми загадочными ошибками компиляции в проверке требований к хешу.
#include <set>
#include <unordered_set>
template <class C, class T>
struct rebind {};
template <class T0, class T>
struct rebind<std::set<T0>, T> {
using type = std::set<T>;
};
template <class T0, class T>
struct rebind<std::unordered_set<T0>, T> {
using type = std::unordered_set<T>;
};
template <class C>
class wrapped_iterator;
template <class C>
using twisted_container = typename rebind<C, wrapped_iterator<C>>::type;
template <class C>
class wrapped_iterator : public twisted_container<C>::iterator {
size_t key() const { return reinterpret_cast<std::uintptr_t>(std::addressof(**this)); }
bool operator < (const wrapped_iterator& other) const { return key() < other.key(); }
bool operator == (const wrapped_iterator& other) const { return key() == other.key(); }
};
namespace std {
template <class C>
struct hash<wrapped_iterator<C>> {
size_t operator()(wrapped_iterator<C> it) const {
return it.key();
}
};
}
int main() {
twisted_container<std::set<int>> a;
twisted_container<std::unordered_set<int>> b; // This doesn't compile!
return 0;
}
Ошибка лягушки:
<source>:24:59: error: no type named 'iterator' in 'std::unordered_set<wrapped_iterator<std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int> > >, std::hash<wrapped_iterator<std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int> > > >, std::equal_to<wrapped_iterator<std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int> > > >, std::allocator<wrapped_iterator<std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int> > > > >'
class wrapped_iterator : public twisted_container<C>::iterator {
~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
Ошибка gcc:
<source>:24:11: error: invalid use of incomplete type 'twisted_container<std::unordered_set<int> >' {aka 'class std::unordered_set<wrapped_iterator<std::unordered_set<int> >, std::hash<wrapped_iterator<std::unordered_set<int> > >, std::equal_to<wrapped_iterator<std::unordered_set<int> > >, std::allocator<wrapped_iterator<std::unordered_set<int> > > >'}
class wrapped_iterator : public twisted_container<C>::iterator {
^~~~~~~~~~~~~~~~
Я пытаюсь сделать что-то незаконное?Есть ли способ исправить эту ошибку?Почему unordered_set
особенный в этом случае?Это предполагаемое поведение или ошибка в реализации компиляторов?