Как я могу использовать gsl :: span и указать владельца?

Я хочу написать функцию, которая:

  1. Принимает указатель в качестве параметра
  2. Принимает длину в качестве параметра
  3. Владеет памятью, на которую указывает указатель (например, может быть, он освобождает ее или создает для него unique_ptr в некоторой структуре данных и т. Д.)

Теперь, если бы я хотел 1 + 2, я бы просто использовал gsl::span, И если бы хотел 1 + 3, я бы использовал owner<T*>, Но что мне делать, когда я хочу все три? Должен ли я пройти owner<gsl::span<T>>? Что-то другое?

3

Решение

Одним из вариантов будет определение собственного абстрактного базового класса для инкапсуляции данных. Что-то вроде:

template<typename T>
class DataHolder {
public:
virtual ~DataHolder() = default;
virtual gsl::span<T> get() const = 0;
};

Тогда ваша функция может выглядеть примерно так:

void foo(std::unique_ptr<DataHolder<int>> data) {
if (!data)
return;
for (auto v : data->get())
std::cout << v << " ";
}

Вызывающая сторона может затем реализовать базовый класс с любым контейнером, который они хотят. Там будет небольшая стоимость полимофизма, но не на основе каждого элемента.

Если вы не хотите платить за полиморфизм, возможно, вы могли бы заставить свою функцию принимать параметр шаблона.

template<typename DataHolder>
void foo(DataHolder data) {
for (auto v : data())
std::cout << v << " ";
}

где неявный интерфейс для DataHolder может быть удовлетворен чем-то вроде:

struct VectorHolder {
std::vector<int> data;
gsl::span<const int> operator()() const { return data; }
};

или если вы действительно не хочу использовать vector, Вы можете использовать что-то вроде этого (как предложено @utnapistim):

struct ArrayHolder {
std::unique_ptr<int[]> data;
ptrdiff_t              length;
gsl::span<const int> operator()() const { return {data.get(), length}; }
};
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]