-1

Is it possible to use constructions like QMap< QString, boost::multi_index_container<...> >?

On the one hand, we have private: BOOST_COPYABLE_AND_MOVABLE(multi_index_container) in the containers declaration. It should tell us not to put multi_index_container<> into other stl-like container.

On the other hand, such construction

QMap< QString, boost::multi_index_container<...> > _map;
map.insert("bla-bla", container1);
...
auto tmp = _map.value(QString("bla-bla")).get<keyVal>();
//keyVal corresponds to one for the multi_index_container instance

is compiled well with Visual Studio 2012 (+update4 + boost v1.55 + qt v4.8.5).

Experimentally it was discovered that:

auto tmp = _map.value(QString("bla-bla")).get<keyVal>();

makes tmp to handle deleted data. while

auto tmp = _map.value(QString("bla-bla"));
auto tmp_1 = tmp.get<keyVal>();

leaves tmp_1 with valid data.

Does anybody know what is the proper treatment with boost::multi_index_container<> if we need to put it in another container?

Are there any differences for Qt5.3?

sehe
  • 374,641
  • 47
  • 450
  • 633
Illia Levandovskyi
  • 1,228
  • 1
  • 11
  • 20
  • _"experimentally you found"_ that compilers will happily compile your [Undefined Behaviour](). They're not required to emit diagnostics messages for the vast majority of such cases. – sehe Oct 07 '14 at 17:25

3 Answers3

3

As you can see in the docs for QMap:

const T QMap::value(const Key & key, const T & defaultValue = T()) const

The value is returned by value, not by reference. Besides being very inefficient for large values (such as multi index containers, maybe?) it also returns a temporary.

Now, get<keyVal>(); does return a reference to the first index, but it's the one that belongs to the temporary, which dies at the end of the containg full-expression.


To get a modifiable reference, use

T & QMap::operator[](const Key & key)

Now you can:

auto& tmp = _map[QString("bla-bla")].get<keyVal>();

Note the &.

sehe
  • 374,641
  • 47
  • 450
  • 633
1

Adding to @sehe's answer on how to retrieve references rather than temporary values, boost::multi_index_container is copyable and movable. This BOOST_COPYABLE_AND_MOVABLE macro you refer to has to be placed on the class private section (as specified here), but that does not affect visibility of copy/movement ctors. Moral of the story: consult docs before diving into the code.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Joaquín M López Muñoz
  • 5,243
  • 1
  • 15
  • 20
-4

In my particular case, the problem was that compiler used const T operator[](const Key & key) const instead of T & operator[](const Key & key) because the method of the class was a const one and the map was a field of the class.

Illia Levandovskyi
  • 1,228
  • 1
  • 11
  • 20
  • 3
    This is not an answer, the code in your question had no such issue, and your types were all deduced by `auto`. The problem you asked about was your **[Undefined Behaviour]()** ("makes `tmp` to handle deleted data") which I explained in my answer. If you fix unrelated things **after** fixing that, well, that's unrelated. – sehe Oct 08 '14 at 14:49
  • the question is not about undefined behavior. the question is about particular case of using boost::multi_index_container instance as QMap value. so my answer is completely relates to the question. as an additional question I've asked some information about boost::multi_index_container implementation. therefore, while quoting to documentation is always useful, it's not directly related to the issue. deducing types by auto is not the origin of the problem, so your comment is not constructive. – Illia Levandovskyi Oct 08 '14 at 18:17
  • "makes tmp to handle deleted data" and "Does anybody know what is the proper treatment" are **exactly** about UB, and actually have **nothing** to do with multi_index. You'd have had precisely the same problem (Undefined Behaviour) with a QMap where you used `auto tmp = map.value(QString("keyname")).c_str()` – sehe Oct 08 '14 at 19:21
  • By the way, deducing the variables as `auto` was relevant, because only `auto&` takes references. The undefined behaviour stems from holding dangling references to temporaries.references). I have the impression you didn't really understand the problem that you were having to solve. – sehe Oct 08 '14 at 19:23