I want to write a function which:
Now, if I wanted 1+2 I would just use gsl::span
. And if wanted 1+3 I would use owner<T*>
. But what should I do when I want all three? Should I pass an owner<gsl::span<T>>
? Something else?
Notes:
std::vector
is requiring too much. The function should not require the caller to construct an std::vector
.One option would be to define your own abstract base class to encapsulate the data. Something like:
template<typename T>
class DataHolder {
public:
virtual ~DataHolder() = default;
virtual gsl::span<T> get() const = 0;
};
Then your function could look something like:
void foo(std::unique_ptr<DataHolder<int>> data) {
if (!data)
return;
for (auto v : data->get())
std::cout << v << " ";
}
The caller can then implement the base class with any container they want to. There will be a small cost of polymophism but not on a per-element basis.
If you don't want to pay for polymorphism, perhaps you could make your function accept a template parameter.
template<typename DataHolder>
void foo(DataHolder data) {
for (auto v : data())
std::cout << v << " ";
}
where the implicit interface for DataHolder
could be satisfied by something like:
struct VectorHolder {
std::vector<int> data;
gsl::span<const int> operator()() const { return data; }
};
or if you really don't want to use vector
. You could use something like this (as suggested by @utnapistim):
struct ArrayHolder {
std::unique_ptr<int[]> data;
ptrdiff_t length;
gsl::span<const int> operator()() const { return {data.get(), length}; }
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With