5

My specific problem is that I have a QMultiHash<Foo,Bar*> private member, and I'd like to provide access to the values of the hash, but to const versions of the items, declaring:

QList<const Bar*> getBars(Foo f) const;

Is there a cleaner/more efficient way of "constifying" the items inside a Qt container than the ugly/inefficient creation of a new container with const items and copying pointers from the source (QMultiHash<K,V>::values() in this case)?

I'm afraid the answer might be "no", but I wanted to make sure I wasn't missing some Qt/C++(03) syntax magic to do that.

eclarkso
  • 1,087
  • 9
  • 21
  • 1
    See http://stackoverflow.com/questions/10265695/treat-vectorint-as-vectorconst-int-without-copying-c0x I don't know a solution (except maybe a huge ugly hack), but is a `for` loop such a big deal? It's simply copying pointers, I doubt it'll impact your performance - unless the `QList` is huge& and you have very high performance requirements. – Armaghast Aug 27 '15 at 13:19
  • Also, check http://stackoverflow.com/questions/2102244/vector-and-const for the reason. – Armaghast Aug 27 '15 at 13:24
  • In this particular case, it's not a big deal (and I've gone ahead and implemented it that way). But it offends my sense of style, and in other instances in my application (interactive data visualization), I could need to do interactive UI operations on containers of ~1000-10000s chart glyph objects wherein I'm inspecting but not changing the glyph objects without lagging the UI just to get a container of const pointers. – eclarkso Aug 27 '15 at 15:44

2 Answers2

0

There are two ways. The obvious way you mention is to use C++11 for and convert it yourself to QList<const Bar*>.

QList<const Bar*> getList() const
{
    QList<const Bar*> list;

    for(Bar *b : m_List) //where m_List is your private memebr QList<Bar*>
        list << b;

    return list;
}

The other way is to convert the QList itself to const QList<Bar*> which can be done "magically" by returning the list from a const function for instance:

const QList<Bar*> getList() const
{ 
    return m_List; //where m_List is your private memebr QList<Bar*>
} 

Which one to use depends on your needs. From what you describe you need to inspect the elements without changing them. That sounds like that you do not actually need the modifiable list at all. The first variant sound like an overkill already. You want const Bar* presumably because you do not want it to change by accident when you inspect the item. To examine all elements for example you could do (adding const automatically for each element):

for(const Bar *b : myObject->getList())
    //do only const stuff with b

Unless you have a really good reason for returning QList<const Bar*> such as that you need the list to be modifiable it is not worth the trouble and performance hit. You can restrict Bar * with const when you access it yourself by using the C++11 for in a way I described or by using const iterators. From what I gather I would recommend using that rather than converting (possibly huge) list(s)' values to const.

And one last tip, if your lists are really huge and you need every drop of performance consider:

const QList<Bar*> &getList() const

The implicit sharing of Qt does this in the previous code snippet on its own I believe but this ensures the list will never be copied or modified when you inspect it.

Resurrection
  • 3,916
  • 2
  • 34
  • 56
  • Note that my actual member is a QMultiHash, and what I want to provide const access to are the list of values from QMultiHash::values()., and as such the last const reference isn't an option. Also note that a major reason for providing such an accessor is for const correctness; plus, I'd prefer not to rely on the good graces of myself or others to access the list (via const iterators et al.) appropriately. – eclarkso Sep 21 '15 at 21:00
  • @eclarkso In that case your only option is to create such a list yourself. Even if there existed a function that would create it for you it would be doing pretty much the same thing - creating new list with const elements. Anyway, use C++11 for to do it as it is the fastest way currently available. Unless you run into performance issues with your inspection taking too long because the list is too big (and conversion takes too long) there should be no problem. If performance does become an issue you will probably have to reconsider your priorities or design. Good luck! – Resurrection Sep 22 '15 at 05:46
0

No effective way to "constifying" objects in existing array. But if you really store list of pointers. May be fast to convert not "const" pointers to "const" pointers in simple cycle?! (I.e. make new list) Second solution is make "const" objects in list initially, when you fill that list. And third way is make own children class of your list what can return only "const" reference or iterator to stored elements.

stanislav888
  • 374
  • 2
  • 9