i try to do ordered map ( simple very simple )
i want to overload the map "[] = value " operator . that is the equal sign that come after the array operator
but how ?
i have this :
template <typename K, class V>
class OrderedMap
{
public:
OrderedMap(){};
~OrderedMap(){};
void setValue(K _k);
void operator[] (K _k);
private:
std::vector<K> insertOrder;
std::tr1::unordered_map<K, V> myTable;
};
template <typename K, class V>
OrderedMap<K, V>::setValue(K _k)
{
myTable[_k];
insertOrder.push_back(_k);
}
template <typename K, class V>
void OrderedMap<K, V>::operator[] (K _k)
{
......
}
i have the array set and working but how to add the option to add value to key via array operator
so this will be vaild
m_Map[CONST1] = "value"
Basically operator[] is a function call which only supplies the parameters inside of the brackets to your class.
So in C++ you actually use the operator[] a bit different than let's say Delphi or C#:
The operator[] usually returns a reference to the item inside the collection:
myContainer[3] = value;
will actually resolve to the following:
MyItem refToObj& = myContainer[3];
refToObj = value;
the operator[] should then have the following form
MyItem& MyContainer::operator[](int);
If you cannot work with references for some reason (for example you don't actually HAVE a MyItem instance inside your container and the operator[] should convert the object into a different type) then the only approach is to use a "helper object":
MyContainer::Helper helper = myContainer[3];
helper = value;
the operator[] should then have the following form
MyContainer::Helper MyContainer::operator[](int);
where MyHelper is a special class which overloads the operator= which then does the container specific conversion (see vector<bool> if you're interested in this approach).
Edit:
To come back to the problem: I'm a bit unsure what you exactly want to accomplish, but I think you'd need to use the "Helper" approach:
class OrderedMap
{
class ItemHelper
{
public:
ItemHelper(OrderedMap& map, K key): m_map(map), m_key(key) {}
//writing a value
V& operator=(const V& v)
{
m_map.setValue(m_key);
m_map.myTable[m_key] = v;
}
//reading a value
operator const V&() { return m_map[k]; }
private:
K m_key;
OrderedMap& m_map;
};
};
Your operator[] needs to return a non-const reference to the indexed element:
V& OrderedMap<K, V>::operator[] (K _k)
In your function body, you need to check if that key is already represented in the map and, if so, return a reference to the corresponding value. If that key is not in the map, default construct a V, add it to the map, then return a reference to the value in the map.
Related
While trying to create a cpp set of objects, I came across this question
How do i insert objects into STL set
But my doubt is that, is there any way to not store actual objects in the set but pointers to them and still be able to maintain the unique entity property of the set.
The set template is parameterised as
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
To store pointers to a type T, yet ensure that the values are unique you simply need to provide an appropriate Compare functor that can compare pointers by comparing their dereferenced values.
For example, for pointers to some_type we could use something like:
class comparison {
bool operator()(const some_type* lhs, const some_type* rhs) const {
return *lhs < *rhs;
}
};
and then declare the set as
std::set<some_type*, comparison> s;
You can use a custom comparator in std::set to de-reference the object and compare.
bool compare_int(const int*& l, const int*& r) {
return (*l) < (*r);
}
std::set<int*, compare_int> intSet;
int myInt = 5;
int* myIntPtr = &myInt;
inSet.insert(myIntPtr);
I have a situation, where I would like to have a map that does not allow to add/remove keys after initialization, but the values are allowed to change (thus I cannot simply make the map const). Ie
/*semi-const*/ map<int,int> myMap = initMap();
myMap[1] = 2; // NOT OK, because potentially adds a new key
myMap.at(1) = 2; // OK, because works only if key is present
for (auto & element : myMap) {
element.second = 0; // OK, values may change
}
I could write my own wrapper for std::map, but I have the feeling that it is something not too uncommon, so I wonder if there is already an existing solution.
Is there some standard idiom for a map that does not allow adding/removing keys, while the values may change?
ps: I know that the title alone is a bit vague, because the keys are already const in a map, but I hope it is clear what I mean...
Could you create a wrapper that contains the value that allows the value to be mutated when const and put that in the map instead? Something like:
template<typename T>
class Mutable {
mutable T value;
public:
const Mutable& operator=(const T& v) const { value = v; return *this; }
T& get() const { return value; }
};
Then your map can be of type
const std::map<int, Mutable<int>>
Live demo.
I usually regard this as a pitfall in C++ more than a feature, but, if it fits your application, you can just use pointer values.
#include <map>
#include <memory>
int main(int argc, char ** argv)
{
using namespace std;
const map<int, shared_ptr<int>> myMap = { {1, make_shared<int>(100)} };
// *(myMap[1]) = 2; // Does not compile
*(myMap.at(1)) = 2;
for (auto & element : myMap)
{
*(element.second) = 0;
}
return 0;
}
Which is really just a simpler version of this other answer (obviously you may choose between shared_ptr / unique_ptr as needed).
Containers from the standard library are classes optimized for one usage that are expected to be used as is or included in higher level classes.
Here your requirement (keys fixed after initialization) is not covered by the standart library containers, so you will have to build your own implementation. As it will not be a std::map, you can just implement the operations you need, probably nothing more that operator []...
I understand that you simply want to disable the index access operator so that a user cannot accidentally add a default constructed item to the map. My solution is inspired by Chris Drew's solution but has the added benefit of remaining const correct (i.e. not allowing changing values of the map when the map is const).
Essentially, by disabling default construction you remove the ability to invoke the index access operator provided by std::map. The other methods will remain available since std::map is a class template and member functions won't be evaluated until they are invoked. Hence, std::map::at will work fine but std::map::operator[] will result in a compile-time error.
Inspired by Chris you can use a wrapper on the mapped_type to disable default construction. I took his demo and tweaked it a bit to demonstrate how to disable default construction and used it with std::map rather than a const std::map.
template<typename T>
class RemoveDefaultConstruction {
T value;
public:
RemoveDefaultConstruction() = delete; // The magic is here
RemoveDefaultConstruction(const RemoveDefaultConstruction &other) noexcept(std::is_nothrow_copy_constructible<T>::value) = default;
RemoveDefaultConstruction(RemoveDefaultConstruction &&other) noexcept(std::is_nothrow_move_constructible<T>::value) = default;
RemoveDefaultConstruction(T &&t) noexcept(std::is_nothrow_constructible<T, decltype(std::forward<T>(t))>::value) :
value{std::forward<T>(t)} {
}
RemoveDefaultConstruction& operator=(const RemoveDefaultConstruction &other) = default;
RemoveDefaultConstruction& operator=(RemoveDefaultConstruction &&other) = default;
RemoveDefaultConstruction& operator=(T &&other) { value = std::move(other); return *this; }
RemoveDefaultConstruction& operator=(T const &other) { value = other; return *this; }
T const &get() const { return value; } // Keep const correctness
T &get() { return value; } // Keep const correctness
};
void update(std::map<int, RemoveDefaultConstruction<int>> &m, int k, int v) { m.at(k) = v; }
void update(std::map<int, RemoveDefaultConstruction<int>> const &m, int k, int v) {
//m.at(k) = v; // ERROR: Cannot change a const value
}
Live Demo
I see 2 options here
Make the map const and use const_cast when changing something
const std::map myMap;
myMap[1] = 2; // NOT OK, because const map
(const_cast&>(myMap)).at(1) = 2; // OK with const_cast
make an wrapper class or derive an custom map that has only read and update existing value methods
I don't think there is an built in way to make an map only with update value, and restrict and insert.
I have a pointer to a:
struct KeyValue {
K key;
V value;
}
and I want to return a reference to the same memory location interpreted as a
struct IKeyValue {
const K key;
V value;
}
Is there a clean way to do it in C++11?
The reference to IKeyValue should be valid as long as any reference to the original KeyValue is valid.
The reason I am doing this is because I am implementing a HashTable<K, V> using open addressing. As a consequence I have an array of KeyValue with some of them being fully constructed (key and value constructed) and some of them half constructed (only key constructed to empty_key or tombstone_key). I want the iterators to this structure be used such that it->key can be read but not modified and it->value can be read and modified. And I prefer not to have something such as it->key() and it->value() as it is done in the standard library.
As it seems difficult to do this, I am thinking of another option as suggested by the answers. I can construct an array of IKeyValue inside my HashTable with:
IKeyValue* p = (IKeyValue*)malloc(n * sizeof(IKeyValue));
But then, am I allowed to use emplacement new in order to construct just a key or a value with placement new?
You can provide reference members and a constructor
struct IKeyValue {
const K& key;
V& value;
IKeyValue(KeyValue& x) : key(x.key), value(x.value) {}
};
But as mentioned in the comment, the lifetime management for the referenced instances could become a problem.
In IKeyValue, use accessor functions rather than data fields:
struct IKeyValue {
private:
KeyValue & keyValue;
public:
IKeyValue (KeyValue & keyValue) : keyValue (keyValue) {}
K const & key () const { return keyValue.key; }
V & value () { return keyValue.value; }
V const & value () const { return keyValue.value; }
};
KeyValue kv = ...;
IKeyValue ikv (kv);
... ikv.key (); // returns kv.key;
ikv.value () = ...; // sets kv.value;
You can't , as they are not the same type, nor IKeyValue is a derived class of KeyValue.
You need to redesign your code to use something different, like returning a view of the class instead.
The cleanest way to do this is to make your data members private, and provide getters and setters when needed. From what you wrote, it seems that you want the key to be read-only, and the value to be read-write. So you can do this:
class KeyValue
{
public:
KeyValue(K k, V v) : key(k), value(v) {}
K get_key() const {return key;}
V get_value() const {return value;}
void set_value(V v) {value = v;}
private:
K key;
V value;
};
Now the key can only be set in the constructor, and is read-only from that moment on.
Okay, this is quite a weird solution I'm offering here, and some would argue an abusive one, but if your "Value" is always modifiable, you could do something like:
struct KeyValue {
K key;
mutable V value;
};
and then hold a const KeyValue& where you want to lock in the constness of the key.
I'm looking for a way to create a forward iterator which allows to iterate over a collection of hash maps.
An exemplary class which holds several maps looks like follows. (I'm using boost for unordered_map and shared_ptr, but C++11 would provide those classes as well).
In my particular application I'm using this construct to represent sparse hierarchical 2D grid locations; i.e. KeyT is a 2D location, ValueT is an integral counter and the different levels represent different resolutions of the grid.
template <typename KeyT, typename ValueT>
class MapCollection
{
public:
// type-definitions for the map and a shared pointer to the map
typedef boost::unordered_map<KeyT, ValueT> Map;
typedef boost::shared_ptr<Map> MapPtr;
// Constructor for class
MapCollection (int num_levels)
{
levels_.reserve (num_levels);
for (int i = 0; i < num_levels; ++i)
levels_.push_back (MapPtr (new Map()));
}
// adds a key-value pair to the map on the given level
void addValue (const KeyT &key, const ValueT &value)
{
int level = getLevelForKey (key);
(*levels_[level])[key] = value;
}
// TODO define const_iterator for this class
// TODO define member function begin(), returning levels_.front()->begin()
// TODO define member function end(), returning levels_.back()->end()
private:
// return the hierarchy level for the given key
int getLevelForKey (const KeyT &key) { return /* ... */ };
// collection of maps
std::vector<MapPtr> levels_;
};
Within an application I would now like to be able to iterate over all entries of all maps, similarly to what is possible if one just iterates over a single map, i.e.
int main (int argc, char *argv[])
{
int num_levels = 5;
MapCollection maps (num_levels);
// fill maps
maps.addValue ( /* ... */ )
// iterator over all entries
MapCollection::const_iterator iter = maps.begin();
for (; iter != maps.end(); ++iter)
{
std::cout << "Key: " << iter->first << " | Value: " << iter->second << std::endl;
}
return EXIT_SUCCESS;
}
Obviously it would be possible to iterator over the different levels and for each level over it's map, but I would like to hide the creation of different levels for the user.
What is the correct way to define an (const_)iterator for the class MapCollection?
Thanks for your help!
You could use boost iterator facade, that will help you with the task of implementing custom iterators. The idea would be:
1-maintain a reference to the vector containing the maps (levels_).
2-a iterator indicating what element of the previous vector the custom iterator is iterating (of type std::vector<MapPtr>::iterator or std::vector<MapPtr>::const_iterator) or a index with the same info (to retrieve the end of level_[index]).
3-a iterator with current element of the iteration of the previous iterator (the actual element of the iteration).
Some sample code:
#include <boost/iterator/iterator_facade.hpp>
namespace impl
{
template <class Value>
class iterator
: public boost::iterator_facade<
config_iterator<Value>
, Value
, boost::forward_traversal_tag
>
{
public:
config_iterator() {...}
explicit config_iterator(parameters) { /*your specific contructor*/ }
private:
template <class OtherValue>
config_iterator(config_iterator<OtherValue> const& other);
friend class boost::iterator_core_access;
template <class> friend class config_iterator;
template <class OtherValue>
bool equal(config_iterator<OtherValue> const& other) const { } // Verify is two iterators are equals (used to verify if it == end)
void increment() {} // Logic for incrementing the iterator
Value& dereference() const {} // Returning the actual value
// members
};
}
typedef impl::iterator<type> iterator;
This is a template file for very simple iterator (forward), read the Iterator Help for more info, the same can be implementing overloading the right operators (++ post a pre increment, *, ->, etc...), by boost provide a ways of defining the minimum necessary to implement the rest.
I am writing a template Polynom<T> class where T is the numeric type of its coefficients.
The coefficients of the polynom are stored in an std::vector<T> coefficients, where coefficients[i] corresponds to x^i in a real polynom. (so the powers of x are in increasing order).
It is guaranteed that coefficients vector always contains at least one element. - for a zero polynom it is T().
I want to overload the operator[] to do the following:
The index passed to the operator[] corresponds to the power of X whose coefficient we want to modify / read.
If the user wants to just read the coefficient, it should throw for negative indices, return coefficients.at(i) for indices within the stored range - and reasonably return 0 for all other indices, not throw.
If the user wants to modify the coefficient, it should throw for negative indices, but let user modify all other indices freely, even if the index specified is bigger than or equal to coefficients.size(). So we want to somehow resize the vector.
The main problem I have collided with is as follows:
1.
How do I distinguish between the read case and the write case? One person left me without an explanation but said that writing two versions:
const T& operator[] (int index) const;
T& operator[] (int index);
was insufficient. However, I thought that the compiler would prefer the const version in the read case, won't it?
2.
I want to make sure that no trailing zeros are ever stored in the coefficients vector. So I somehow have to know in advance, "before" I return a mutable T& of my coefficient, what value user wants to assign. And I know that operator[] doesn't receive a second argument.
Obviously, if this value is not zero (not T()), then I have to resize my vector and set the appropriate coefficient to the value passed.
But I cannot do it in advance (before returning a T& from operator[]), because if the value to be assigned is T(), then, provided I resize my coefficients vector in advance, it will eventually have lots of trailing "zeroes".
Of course I can check for trailing zeroes in every other function of the class and remove them in that case. Seems a very weird decision to me, and I want every function to start working in assumption that there are no zeroes at the end of the vector if its size > 1.
Could you please advise me as concrete solution as possible to this problem?
I heard something about writing an inner class implicitly convertible to T& with overloaded operator=, but I lack the details.
Thank you very much in advance!
One option you could try (I haven't tested this):
template<typename T>
class MyRef{
private:
int index;
Polynom<T>*p;
public:
MyRef(int index, Polynom<T>*p) : index(index), p(p) { }
MyRef<T>& operator=(T const&t); //and define these appropriately
T operator T() const;
};
and define:
MyRef<T> operator[](int index){
return MyRef<T>(index, this);
}
This way when you assign a value to the "reference" it should have access to all the needed data in the polynomial, and take the appropriate actions.
I am not familiar enough with your implementation, so I'll instead give an example of a very simple dynamic array that works as follows:
you can read from any int index without concern; elements not previously written to should read off as 0;
when you write to an element past the end of the currently allocated array, it is reallocated, and the newly allocated elements are initialized to 0.
#include <cstdlib>
#include <iostream>
using namespace std;
template<typename T>
class my_array{
private:
T* _data;
int _size;
class my_ref{
private:
int index;
T*& obj;
int&size;
public:
my_ref(T*& obj, int&size, int index)
: index(index), obj(obj), size(size){}
my_ref& operator=(T const& t){
if (index>=size){
obj = (T*)realloc(obj, sizeof(T)*(index+1) );
while (size<=index)
obj[size++]=0;
}
obj[index] = t;
return *this;
}
//edit:this one should allow writing, say, v[1]=v[2]=v[3]=4;
my_ref& operator=(const my_ref&r){
operator=( (T) r);
return *this;
}
operator T() const{
return (index>=size)?0:obj[index];
}
};
public:
my_array() : _data(NULL), _size(0) {}
my_ref operator[](int index){
return my_ref(_data,_size,index);
}
int size() const{ return _size; }
};
int main(){
my_array<int> v;
v[0] = 42;
v[1] = 51;
v[5] = 5; v[5]=6;
v[30] = 18;
v[2] = v[1]+v[5];
v[4] = v[8]+v[1048576]+v[5]+1000;
cout << "allocated elements: " << v.size() << endl;
for (int i=0;i<31;i++)
cout << v[i] << " " << endl;
return 0;
}
It's a very simple example and not very efficient in its current form but it should prove the point.
Eventually you might want to overload operator& to allow things like *(&v[0] + 5) = 42; to work properly. For this example, you could have that operator& gives a my_pointer which defines operator+ to do arithmetic on its index field and return a new my_pointer. Finally, you can overload operator*() to go back to a my_ref.
The solution to this is a proxy class (untested code follows):
template<typename T> class Polynom
{
public:
class IndexProxy;
friend class IndexProxy;
IndexProxy operator[](int);
T operator[](int) const;
// ...
private:
std::vector<T> coefficients;
};
template<typename T> class Polynom<T>::IndexProxy
{
public:
friend class Polynom<T>;
// contrary to convention this assignment does not return an lvalue,
// in order to be able to avoid extending the vector on assignment of 0.0
T operator=(T const& t)
{
if (theIndex >= thePolynom.coefficients.size())
thePolynom.coefficients.resize(theIndex+1);
thePolynom.coefficients[theIndex] = t;
// the assignment might have made the polynom shorter
// by assigning 0 to the top-most coefficient
while (thePolynom.coefficients.back() == T())
thePolynom.coefficients.pop_back();
return t;
}
operator T() const
{
if (theIndex >= thePolynom.coefficients.size())
return 0;
return thePolynom.coefficients[theIndex];
}
private:
IndexProxy(Polynom<T>& p, int i): thePolynom(p), theIndex(i) {}
Polynom<T>& thePolynom;
int theIndex;
}
template<typename T>
Polynom<T>::IndexProxy operator[](int i)
{
if (i < 0) throw whatever;
return IndexProxy(*this, i);
}
template<typename T>
T operator[](int i)
{
if (i<0) throw whatever;
if (i >= coefficients.size()) return T();
return coefficients[i];
}
Obviously the code above is not optimized (especially the assignment operator has clearly room for optimization).
You cannot distinguish between read and write with operator overloads. The best you can do is distinguish between usage in a const setting and a non-const setting, which is what your code snippet does. So:
Polynomial &poly = ...;
poly[i] = 10; // Calls non-const version
int x = poly[i]; // Calls non-const version
const Polynomial &poly = ...;
poly[i] = 10; // Compiler error!
int x = poly[i] // Calls const version
It sounds like the answer to both your questions, therefore, is to have separate set and get functions.
I see two solutions to your problem:
Instead of storing the coefficients in a std::vector<T> store them in a std::map<unsigned int, T>. This way you will ever only store non-zero coefficients. You could create your own std::map-based container that would consume zeros stored into it. This way you also save some storage for polynomials of the form x^n with large n.
Add an inner class that will store an index (power) and coefficient value. You would return a reference to an instance of this inner class from operator[]. The inner class would overwrite operator=. In the overridden operator= you would take the index (power) and coefficient stored in inner class instance and flush them to the std::vector where you store your coefficients.
This is not possible. The only way I can think of is to provide a special member-function for adding new coefficients.
The compiler decides between the const and non-const version by looking at the type of Polynom, and not by checking what kind of operation is performed on the return-value.