patterncppMinor
Simple sparse array
Viewed 0 times
arraysimplesparse
Problem
Today, I tried to create a really simple
What I tried to do is to have a sparse array whose number of elements is strictly equal to the number of elements that are different from
```
#include
int main
sparse_array container adapter. I did not provide all the STL-like functions, only the elementary ones as a proof of concept. I also trimmed the class from its copy constructor and all the unecessary things for this review actually. Here is the code:#include
#include
template class Container=std::map>
struct sparse_array
{
class proxy
{
sparse_array& sp;
std::size_t index;
proxy(sparse_array& sp, std::size_t index):
sp(sp),
index(index)
{}
public:
proxy(const proxy& other) = default;
auto operator=(const proxy& other)
-> proxy&
{
sp.data[index] = T(other);
return *this;
}
auto operator=(const T& val)
-> proxy&
{
if (val != sp.default_value)
{
sp.data[index] = val;
}
else
{
sp.data.erase(index);
}
return *this;
}
operator T() const
{
auto res = sp.data.find(index);
if (res != sp.data.end())
{
return res->second;
}
return sp.default_value;
}
friend class sparse_array;
};
auto operator[](std::size_t index)
-> proxy
{
return { *this, index };
}
auto operator[](std::size_t index) const
-> const proxy
{
return { *this, index };
}
auto size() const
-> std::size_t
{
return data.size();
}
private:
T default_value = {};
Container data;
};What I tried to do is to have a sparse array whose number of elements is strictly equal to the number of elements that are different from
default_value, hence the elements that are deleted when default_value is assigned to them. Here comes a small example:```
#include
int main
Solution
The primary question I have is one of usage. By the name
It needs to be clear what the output from that would be. Would it include the default values in most indices? Or is this usage prohibited (perhaps due to that unclarity), as currently there are no iterator related methods? Maybe this is just part of what you intentionally excluded from the review, but it leaves so much unanswered, including things that probably come back to your proxy class, such as how
The one definite gap I see has to do with
Other comments:
sparse_array, it sounds like you want to expose an interface that is similar to an array. Perhaps it needs dynamic sizing, or perhaps not, but in particular I expect to be able to iterate over its elements with code like this:sparse_array sp;
// ::: fill array here :::
for (int elt: sp)
std::cout out_it(std::cout, ", ");
std::copy(std::begin(sp), std::end(sp), out_it);It needs to be clear what the output from that would be. Would it include the default values in most indices? Or is this usage prohibited (perhaps due to that unclarity), as currently there are no iterator related methods? Maybe this is just part of what you intentionally excluded from the review, but it leaves so much unanswered, including things that probably come back to your proxy class, such as how
*std::begin(sp) = 3 will work.The one definite gap I see has to do with
operator&. Will you support code that looks like normal array-style addressing? Right now the following code will certainly not work correctly; should it fail to compile, or should it modify sp[5]?auto spot = &sp[4];
*(spot + 1) = 5;Other comments:
- I think your proxy approach here is justified for the usage you want to offer.
- It's unclear what values are permissible as alternatives to
std::mapfor yourContainer. Perhaps this is because there are no comments anywhere.
- You aren't completely consistent about use of parentheses vs. braces for initialization. For example,
proxy's constructor uses parentheses where I believe it should use braces:proxy(sparse_array& sp, std::size_t index) : sp{sp}, index{index}
- It's plausible that
default_valueshould be exposed in the template as well, rather than relying on its type's default.
- I'm not yet sold on
auto method_name(params) -> result_typewhenresult_typeis a simple known type. It's too different from theresult_type method_name(params)that I've been using for so many years.
Code Snippets
sparse_array<int> sp;
// ::: fill array here :::
for (int elt: sp)
std::cout << elt << ", ";
// or better
std::ostream_iterator<int> out_it(std::cout, ", ");
std::copy(std::begin(sp), std::end(sp), out_it);auto spot = &sp[4];
*(spot + 1) = 5;Context
StackExchange Code Review Q#43643, answer score: 5
Revisions (0)
No revisions yet.