Reputation: 64925
A recent discussion led me to the question:
Do immutable containers exist in C++? Alternately, since C++ prefers iterators to generalized containers, do immutable iterators exist?
I'm talking about something like the equivalent of Guava's ImmutableList
or the built-in Collections.unmodifiable*
methods. To be clear, those two types of collections are very different - the former is inherently immutable, while the latter is only immutable by actors who get the unmodifiable reference, but is potentially modifiable by actors who have access to the unwrapped object.
I'm interested to know if there is a standardized (actual or de-facto, as in Guava) equivalent to ImmutableCollection
:
or to ret ro = Colletions.unmodifiableCollection(orginalCollection)
(and related methods):
originalCollection
but not by anyone with the return value ro
. Usually it is implemented by wrapping the original collection in a proxy that prevents any modification, but other implementations are possible.I'm well aware of const std::iterator
and friends, but this is very different - it ensures that the a caller can pass an object to a callee, and the object won't modify it, but it does not guarantee to the callee that the object won't be modified.
Now I'm a long-time C++ user here, although admittedly not in the last 5 years, and I couldn't come up with the obvious equivalent.
Upvotes: 7
Views: 2373
Reputation: 19239
There's a project called immer which might be able to handle this this need:
"immutable and persistent data structures for C++"
https://github.com/arximboldi/immer
Upvotes: 2
Reputation: 21576
No, there is no such Container in C++, but its really easy to do such on two levels... First is being const
correct with the object's class you want to store, Second is by using a const reference or pointer to the container you want. Example:
#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;
class Cow {
public:
Cow() : name("default") {}
Cow(string Name) : name(Name) {}
string shout() const { return name; }
private:
string name;
};
int main() {
vector<unique_ptr<const Cow>> mc;
Cow mm("Lol");
mc.push_back(make_unique<const Cow>(Cow()));
mc.push_back(make_unique<const Cow>(Cow("haha")));
mc.push_back(make_unique<const Cow>(mm));
const auto& mcc = mc; //here, your immutable reference
for(auto& x : mcc)
cout << x.get()->shout() << " - - ";
return 0;
}
I am using a std::unique_ptr
here because, its almost certainly useless to use vector<const Cow> mc
.
This portion, const auto& mcc = mc;
from here, take mcc
as your immutable container... You can't add or modify it's elements via any legal means, except of cause casting away const
...
This applies to all other containers I know.
Still on Stackoverflow, See Immutable C++ container class and Immutable container with mutable content
A side note: Also, if the class you want to use is const
incorrect, create a cheap wrapper class that is const
correct then use the wrapper.
Upvotes: 0