Невозможно удовлетворить требования диапазона C++ к пользовательскому контейнеруC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Невозможно удовлетворить требования диапазона C++ к пользовательскому контейнеру

Сообщение Anonymous »

Я пытался написать собственный контейнер с собственным итератором, который можно использовать как диапазон и с std::span. Я новичок в диапазонах, поэтому будьте любезны.
Следующий пример не удалось скомпилировать, поскольку мой класс контейнера невозможно преобразовать в std::span

Код: Выделить всё

#include
#include
#include

template
class MyContainer
{
public:
class ConstIterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = size_t;
using pointer = T* const;
using reference = const T&;

ConstIterator() = default;
ConstIterator(const ConstIterator &other) = default;

ConstIterator(pointer ptr)
: m_ptr(ptr)
{}

reference operator*() const
{
return *m_ptr;
}
pointer operator->()
{
return m_ptr;
}
// Prefix increment
ConstIterator& operator++()
{
m_ptr++;
return *this;
}
// Postfix increment
ConstIterator operator++(int)
{
Iterator tmp = *this;
++(*this);
return tmp;
}
// Prefix decrement
ConstIterator& operator--()
{
m_ptr--;
return *this;
}
// Postfix decrement
ConstIterator operator--(int)
{
Iterator tmp = *this;
--(*this);
return tmp;
}
ConstIterator& operator+=(const difference_type offset) noexcept
{
m_ptr += offset;
return *this;
}

ConstIterator operator+(const difference_type offset) const noexcept
{
ConstIterator tmp = *this;
tmp += offset;
return tmp;
}

ConstIterator& operator-=(const difference_type offset) noexcept
{
return *this += -offset;
}

ConstIterator operator-(const difference_type offset) const noexcept
{
ConstIterator tmp = *this;
tmp -= offset;
return tmp;
}

difference_type operator-(const ConstIterator& right) const noexcept
{
compatible(right);
return m_ptr - right.m_ptr;
}

reference operator[](const difference_type offset) const noexcept
{
return *(*this + offset);
}
bool operator==(const ConstIterator& right) const noexcept
{
return (*this == right);
}
bool operator!=(const ConstIterator& right) const noexcept
{
return !(*this == right);
}

bool operator(const ConstIterator& right) const noexcept
{
return right < *this;
}

bool operator=(const ConstIterator& right) const noexcept
{
return !(*this < right);
}
protected:
T* m_ptr;
};
class Iterator : public ConstIterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = size_t;
using pointer = T*;
using reference = T&;

Iterator() = default;
Iterator(const Iterator &other) = default;

Iterator(pointer ptr)
: ConstIterator(ptr)
{}

reference operator*() const
{
return *ConstIterator::m_ptr;
}
pointer operator->()
{
return ConstIterator::m_ptr;
}
// Prefix increment
Iterator&  operator++()
{
ConstIterator::m_ptr++;
return *this;
}
// Postfix increment
Iterator operator++(int)
{
Iterator tmp = *this;
++(*this);
return tmp;
}
// Prefix decrement
Iterator& operator--()
{
ConstIterator::m_ptr--;
return *this;
}
// Postfix decrement
Iterator operator--(int)
{
Iterator tmp = *this;
--(*this);
return tmp;
}
Iterator& operator+=(const difference_type offset) noexcept
{
ConstIterator::_Verify_offset(offset);
ConstIterator::m_ptr += offset;
return *this;
}

Iterator operator+(const difference_type offset) const noexcept
{
Iterator tmp = *this;
tmp += offset;
return tmp;
}

Iterator& operator-=(const difference_type offset) noexcept
{
return *this += -offset;
}

Iterator operator-(const difference_type offset) const noexcept
{
Iterator tmp = *this;
tmp -= offset;
return tmp;
}

difference_type operator-(const ConstIterator& right) const noexcept
{
compatible(right);
return ConstIterator::m_ptr - right.m_ptr;
}

reference operator[](const difference_type offset) const noexcept
{
return *(*this + offset);
}
};
public:
using value_type = T;
using allocator_type = Allocator;
using pointer = typename std::allocator_traits::pointer;
using const_pointer = typename std::allocator_traits::const_pointer;
using reference = value_type &;
using const_reference = const value_type &;
using size_type = typename std::vector::size_type;
using difference_type = typename std::vector::difference_type;
using iterator = Iterator;
using const_iterator = ConstIterator;
using reverse_iterator = typename std::reverse_iterator;
using const_reverse_iterator = typename std::reverse_iterator;

MyContainer()
{
m_data.resize(10);
}
iterator begin()
{
return iterator(&m_data[0]);
}
iterator end()
{
return iterator(&m_data[0]+m_data.size());
}
const_iterator begin() const
{
return const_iterator(&m_data[0]);
}
const_iterator end() const
{
return const_iterator(&m_data[0]+m_data.size());
}
/*
//These versions of begin() and end() work
T* begin()
{
return &m_data[0];
}
T* end()
{
return &m_data[0]+m_data.size();
}
T* const begin() const
{
return &m_data[0];
}
T* const end() const
{
return &m_data[0]+m_data.size();
}*/
private:
std::vector m_data;
};

int getSum(std::spans)
{
int result =0;
for (int val : s)
result += val;
return result;
}

int main()
{
MyContainer  data;
int sum = getSum(data);
}
Извините, это длинный минимальный пример, но я понимаю, что пользовательский итератор должен предоставлять все необходимые функции для работы с std::span.
Ошибка компиляции, которую я получаю от clang:

Код: Выделить всё

:282:12: error: no matching function for call to 'getSum'
int sum = getSum(data);
^~~~~~
:271:5: note: candidate function not viable: no known conversion from 'MyContainer' to 'std::span' for 1st argument
int getSum(std::spans)
^
1 error generated.
Или из VS2019

Код: Выделить всё

(282): error C2664: 'int getSum(std::span)': cannot convert argument 1 from 'MyContainer' to 'std::span'
(282): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
(271): note: see declaration of 'getSum'
Clang изначально выдавал мне ошибки о неудовлетворении требованиям для всех различных типов диапазонов, вплоть до диапазонов ввода и вывода включительно, и это ссылалось на _Begin. Но когда я вернул код в этот пример, сообщение стало менее подробным.
Это заставило меня подумать, что у меня проблема с моим итератором. Если вместо возврата собственного итератора я просто возвращаю необработанный указатель, код компилируется нормально.
Можно ли как-нибудь выяснить, почему мой код не работает? Я изо всех сил пытаюсь найти подходящее руководство по всему этому, которое было бы понятно новичку в диапазонах.

Подробнее здесь: https://stackoverflow.com/questions/692 ... -container
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»