Thanks yeye_olive
Can you look on my implementation? I tested this code and think that it works fine.
class Container
{
public:
Container();
void setData(const Data &data);
using value_type = Data;
using inner_range = QHash<QString, value_type>;
using outer_range = QHash<QString, inner_range>;
class iterator : std::iterator_traits<inner_range::iterator>
{
public:
using iterator_category = std::forward_iterator_tag;
iterator(outer_range::iterator const & outer_iterator,
outer_range::iterator const & outer_end)
: outer_iterator(outer_iterator), outer_end(outer_end)
{
update();
}
iterator & operator++()
{
++inner_iterator;
if(inner_iterator == inner_end)
{
++outer_iterator;
update();
}
return *this;
}
value_type operator*() const
{
return *inner_iterator;
}
bool operator==(iterator const & rhs) const
{
bool lhs_end = outer_iterator == outer_end;
bool rhs_end = rhs.outer_iterator == rhs.outer_end;
if(lhs_end && rhs_end)
return true;
if(lhs_end != rhs_end)
return false;
return outer_iterator == rhs.outer_iterator
&& inner_iterator == rhs.inner_iterator;
}
bool operator!=(iterator const &other) const
{
return !(*this == other);
}
private:
outer_range::iterator outer_iterator, outer_end;
inner_range::iterator inner_iterator, inner_end;
void update()
{
while(outer_iterator != outer_end)
{
inner_iterator = (*outer_iterator).begin();
inner_end = (*outer_iterator).end();
if(inner_iterator == inner_end)
++outer_iterator;
else
break;
}
}
};
Container::iterator begin();
Container::iterator end();
private:
QHash<QString, QHash<QString, Data>> d;
};
class Container
{
public:
Container();
void setData(const Data &data);
using value_type = Data;
using inner_range = QHash<QString, value_type>;
using outer_range = QHash<QString, inner_range>;
class iterator : std::iterator_traits<inner_range::iterator>
{
public:
using iterator_category = std::forward_iterator_tag;
iterator(outer_range::iterator const & outer_iterator,
outer_range::iterator const & outer_end)
: outer_iterator(outer_iterator), outer_end(outer_end)
{
update();
}
iterator & operator++()
{
++inner_iterator;
if(inner_iterator == inner_end)
{
++outer_iterator;
update();
}
return *this;
}
value_type operator*() const
{
return *inner_iterator;
}
bool operator==(iterator const & rhs) const
{
bool lhs_end = outer_iterator == outer_end;
bool rhs_end = rhs.outer_iterator == rhs.outer_end;
if(lhs_end && rhs_end)
return true;
if(lhs_end != rhs_end)
return false;
return outer_iterator == rhs.outer_iterator
&& inner_iterator == rhs.inner_iterator;
}
bool operator!=(iterator const &other) const
{
return !(*this == other);
}
private:
outer_range::iterator outer_iterator, outer_end;
inner_range::iterator inner_iterator, inner_end;
void update()
{
while(outer_iterator != outer_end)
{
inner_iterator = (*outer_iterator).begin();
inner_end = (*outer_iterator).end();
if(inner_iterator == inner_end)
++outer_iterator;
else
break;
}
}
};
Container::iterator begin();
Container::iterator end();
private:
QHash<QString, QHash<QString, Data>> d;
};
To copy to clipboard, switch view to plain text mode
anda_skoa
And be aware that using a ranged for on a Qt container will require the Qt container to do a deep copy if it is used in more than one variable at the time of iteration.
What exactly you mean?
When I use this container like that:
for( const Data &x : d )
qDebug()<< x.scope << "::" << x.name << ", " << x.value;
for( const Data &x : d )
qDebug()<< x.scope << "::" << x.name << ", " << x.value;
To copy to clipboard, switch view to plain text mode
then it should not create a copy of each elemenet.
And importan question, whether i should stay with QHash whether I can obtain better performance using QMap?
Especially when keys are type of QString which can have between one to over a dozen characters and when each Container should have average 1 <= x <= 30 properties as Data.
Bookmarks