0

The following situation: I am supposed to implement an API, which is getting tuples, and has to store them. Some member of these values are const&, because I am not supposed to change them (& because they are big).

So, I store them in a vector. But I also want to remove them from my vector again. But this, does not work, because I get the following error.

/usr/include/c++/5/tuple:299:17: error: assignment of read-only location ‘std::_Tuple_impl<_Idx, _Head, _Tail ...>::_M_head<0ul, const int&, {double}>(((std::_Tuple_impl<0ul, const int&, double>)this))’

Here a simplified variation of what I am doing:

#include <vector>
#include <tuple>
#include <algorithm>

using xxx = std::tuple<const int&, double>; 

//not allowed to modify integer
void storeTupleWithValue(std::vector<xxx>& values, const int& value){ 
    values.push_back(std::tuple<const int&, double>(value, 3.0));
}

//not allowed to modify integer
void deleteStoredTupleWithValue(std::vector<xxx>& values, const int& value){ 

    //find iterator of "value"
    //...
    auto toDelete = values.begin();

    values.erase(toDelete);
}

const int& produceItem(int& s){
    return s;
} 

int main()
{
    std::vector<xxx> values;
    int s = 5;
    auto apiItem = produceItem(s)

    storeTupleWithValue(values, s);
    deleteStoredTupleWithValue(values, s);
}

So, how do I best resolve this situation, respectively manage to delete my memorized tuples again.

Playground of the code with the error message: https://onlinegdb.com/ry2t_Q5zV

JFFIGK
  • 632
  • 1
  • 7
  • 24
  • Possibly `std::unique_ptr>` ? – Jarod42 Jan 14 '19 at 15:08
  • you mean I shall store unique_ptrs of tuples which I am being passed by value? – JFFIGK Jan 14 '19 at 15:09
  • It seems a viable possibility. – Jarod42 Jan 14 '19 at 15:10
  • it seems like a possibility, but really awkward – JFFIGK Jan 14 '19 at 15:14
  • 1
    At the same time, storing an object like this by const ref, making them constructor only feels also awkward. – Matthieu Brucher Jan 14 '19 at 15:16
  • You could encapsulate the vector in a class and store non-const elements but provide const-iterators for external classes to access the elements. Example: [How to return a private pointer to a list of pointers as const?](https://stackoverflow.com/a/54127343/7582247) – Ted Lyngmo Jan 14 '19 at 15:18
  • @MatthieuBrucher I edited the code a little bit. How else would I store it, given a Interface like "produceItem"? – JFFIGK Jan 14 '19 at 15:21
  • Who is in charge of the memory management of this entry? Maybe the entry int he tuple should be a unique_ptr instead of the whole tuple? – Matthieu Brucher Jan 14 '19 at 15:22
  • While very a unpopular (often for good reasons) `std:list` never moves it's elements and can work well for unmovable types. `std::vector>` is often the preferred solution, but in both cases you throw away locality. – François Andrieux Jan 14 '19 at 15:24
  • @MatthieuBrucher it's not me - I only use the information of the tuple – JFFIGK Jan 14 '19 at 15:24
  • I would have a good chat with the architect of your application. – Matthieu Brucher Jan 14 '19 at 15:24
  • You can copy the remaining elements to a new `vector` and `std::move` it into the existing `values`. – j6t Jan 14 '19 at 15:25
  • 2
    Maybe change reference to pointer: `std::tuple` or reference wrapper: `std::tuple, double>` ? – Jarod42 Jan 14 '19 at 15:26
  • 3
    I was just going to write that `using xxx = std::tuple, double>;` works, if possible. – Bartek Banachewicz Jan 14 '19 at 15:27
  • @MatthieuBrucher What's bad with passing/returning a const& if the client should not modify my item? @ j6t possibly a solution - but a meaningful one? @ Jarod42 @ BartekBanachewicz didn't know about that, I'll try that – JFFIGK Jan 14 '19 at 15:30
  • @JFFIGK Usually you give a const-view of your container, you don't make the element themselves `const`, e.g., you could provide a `const std::vector>&`, and if you need to provide a single element, you provide a const-reference to the original element. – Holt Jan 14 '19 at 16:05
  • if I have a value (original element) of type `const int&`, how would I create a tuple of `tuple` of that? (in storeTupleWithValue), or pass it to a function which takes `tuple`? – JFFIGK Jan 14 '19 at 18:20
  • @ Jarod42 @ BartekBanachewicz I am using the referene_wrapper now, and it works so far. Thanks! Maybe one of you wants to write an answer. @Holt I Still would be interested in your imporovement, which (if it makes sense and works) would be even better. – JFFIGK Jan 14 '19 at 18:50

0 Answers0