comparator for nested map - c++

I have a map which contains another map as value.
Outer map contains string names/custom class (in this example i took name as example), inside map contain datetime and value.
I want CompareNames to be running for outer map and CompareDateTime to be running for inside map. Can i please get some help with what am i doing wrong while passing the comparators to the MyMap initializer list in struct A.
#include <iostream>
#include <map>
#include <locale>
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
enum class ComparePoilicy
{
custom1,
custom2
};
struct CompareNames
{
explicit CompareNames(ComparePoilicy policy)
: policy(policy)
{}
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
{
if (policy == ComparePoilicy::custom1)
{
return lhs < rhs;
}
else
{
return lhs > rhs;
}
}
ComparePoilicy policy;
};
struct CompareDateTime
{
explicit CompareDateTime(ComparePoilicy policy)
: policy(policy)
{}
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
{
const boost::posix_time::ptime timelhs =
boost::posix_time::time_from_string(lhs);
const boost::posix_time::ptime timerhs =
boost::posix_time::time_from_string(rhs);
if (policy == ComparePoilicy::custom1)
{
return timelhs < timerhs;
}
else
{
return timelhs > timerhs;
}
}
ComparePoilicy policy;
};
struct A
{
explicit A(ComparePoilicy dateTime, ComparePoilicy names)
: MyMap( CompareNames(names), CompareDateTime(dateTime))
{}
void fillMe()
{
MyMap["alpha"]["1981-08-20 08:05:00"] = 1;
MyMap["alpha"]["1981-08-20 10:05:00"] = 1;
MyMap["alpha"]["1981-08-20 09:05:00"] = 1;
MyMap["gamma"]["1981-08-20 08:05:00"] = 1;
MyMap["gamma"]["1981-08-20 10:05:00"] = 1;
MyMap["gamma"]["1981-08-20 09:05:00"] = 1;
MyMap["beta"]["1981-08-20 08:05:00"] = 1;
MyMap["beta"]["1981-08-20 10:05:00"] = 1;
MyMap["beta"]["1981-08-20 09:05:00"] = 1;
}
void printMe()
{
for (auto& item : MyMap)
{
for (auto& entry : item.second)
{
std::cout << item.first << " : " << entry.first << " : " << entry.second << std::endl;
}
}
}
std::map<std::string, std::map<std::string, int, CompareDateTime>, CompareNames> MyMap;
};
int main()
{
A test(ComparePoilicy::custom1, ComparePoilicy::custom2);
test.fillMe();
test.printMe();
return 0;
}
colliru link: http://coliru.stacked-crooked.com/a/2bdfbf3bd96ed17e
i tried searching for simillar issues, reading https://en.cppreference.com/w/cpp/container/map/map and trying to get the solution and playing with the initializer list in struct A.

In short, to use std::map::operator[], the mapped type must be default constructible and your std::map uses a comparator that is not.
You can work around it by a avoiding member functions that require the mapped type to be default constructible:
struct A {
explicit A(ComparePoilicy dateTime, ComparePoilicy names) :
MyMap(CompareNames(names)),
m_dateTime(dateTime) // store for when inner maps are to be created
{}
// a helper function to insert values with a properly initialized comparator
void add_one(const std::string& key1, const std::string& key2, int val) {
if(not MyMap.contains(key1)) {
MyMap.emplace(key1,
std::map<std::string, int, CompareDateTime>
(CompareDateTime(m_dateTime)));
}
// using std::map::at is one way to avoid the problem:
MyMap.at(key1).emplace(key2, val);
}
void fillMe() {
// using the helper function:
add_one("alpha", "1981-08-20 08:05:00", 1);
add_one("beta", "1981-08-20 08:05:00", 1);
add_one("gamma", "1981-08-20 08:05:00", 1);
}
std::map<std::string,
std::map<std::string, int, CompareDateTime>, CompareNames> MyMap;
// to store the comparator argument for the inner maps:
ComparePoilicy m_dateTime;
};
Demo

Related

C++ - How to determine the type of the return value of a function?

I'm trying to build a vector of objects that have two properties, the key is always a String, and the value is always of type T
When I iterate through the vector, I need to be able to determine the type of the value property so that I can switch in a case statement to process it.
How do I determine the type of the return value of value get function of the vector object?
My class is here:
template <class T>
class IEFIAttribute
{
String key;
T value;
public:
IEFIAttribute(String key, T value)
{
this->key = key;
this->value = value;
}
String getKey();
T getValue();
};
template <class T>
String IEFIAttribute<T>::getKey()
{
return this->key;
}
template <class T>
T IEFIAttribute<T>::getValue()
{
return this->value;
}
And in my main.cpp, the following works:
...
IEFIAttribute <String> att("testkey","testvalue");
Serial.println("XXX Key: "+att.getKey());
Serial.println("XXX Value: "+att.getValue());
...
The result of running that is:
XXX Key: testkey
XXX Value: testvalue
What I want to be able to do is switch on the type of att.getValue() so that if it is a String, I do one thing, if it is xyz object, I process it according to my rules for xyz objects.
Any help will be very appreciated!
Kind regards!
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
using String = std::string;
template<class T>
class IEFIAttribute {
public:
using value_type = T; // add this to be able to query it later
IEFIAttribute(const String& Key, const T& Value) :
key(Key), // prefer using the member initializer list
value(Value)
{}
// instead of copies, return const references
String const& getKey() const {
return key;
};
T const& getValue() const {
return value;
}
private:
String key;
T value;
};
You have many possibilities to do special handling for certain types.
A template using constexpr if:
template<typename T>
T special_1(const std::vector<IEFIAttribute<T>>& v, size_t idx) {
if constexpr(std::is_same_v<T, String>) {
std::cout << "special_1() String handler\n";
} else if constexpr(std::is_same_v<T, int>) {
std::cout << "special_1() int handler\n";
} else {
std::cout << "special_1() generic handler\n";
}
return v[idx].getValue();
}
A template with specializations:
template<typename T>
T special_2(const std::vector<IEFIAttribute<T>>& v, size_t idx) {
std::cout << "special_2() generic handler\n";
return v[idx].getValue();
}
template<>
String special_2(const std::vector<IEFIAttribute<String>>& v, size_t idx) {
std::cout << "special_2() String handler\n";
return v[idx].getValue();
}
template<>
int special_2(const std::vector<IEFIAttribute<int>>& v, size_t idx) {
std::cout << "special_2() int handler\n";
return v[idx].getValue();
}
Or using the added value_type to do queries:
int main() {
std::vector<IEFIAttribute<String>> v1{{"testkey", "testvalue"}};
std::vector<IEFIAttribute<int>> v2{{"testkey", 10}};
// decltype(v1)::value_type is the vectors value_type
// and the second value_type is the one added to your class
if(std::is_same_v<decltype(v1)::value_type::value_type, String>) {
std::cout << "is String\n";
} else {
std::cout << "is not String\n";
}
if(std::is_same_v<decltype(v2)::value_type::value_type, int>) {
std::cout << "is int\n";
} else {
std::cout << "is not int\n";
}
std::cout << special_1(v1, 0) << "\n";
std::cout << special_1(v2, 0) << "\n";
std::cout << special_2(v1, 0) << "\n";
std::cout << special_2(v2, 0) << "\n";
}
One way to accomplish what you need is to use a typedef inside your class, and then functions of <type_traits> for you conditional statements.
For example:
template <class T>
class IEFIAttribute
{
public:
typedef T value_type;
// everything as before...
};
then
if (std::is_same<att::value_type, String>)
// .. do something

C++ - Map of Vectors of Smart Pointers - All inherited from the same base class

I've got this Map in my Entity-Component-System:
std::map<u_int32_t, std::vector<std::shared_ptr<Component>>> _componentMap;
The u_int32_t is the key to a vector of components. There can be multiple instances of the same component. (That's why there's a vector).
Now I would like to have a templated getter-function that returns a Vector of an inherited type:
template<class T> inline const std::vector<std::shared_ptr<T>> & getVector() const
{
u_int32_t key = getKey<T>();
return static_cast<std::vector<std::shared_ptr<T>>>(_componentMap.count(key) ? _componentMap.at(key) : _emptyComponentVec);
}
I know that this doesn't work, since std::vectors of different types are completely unrelated and I cannot cast between them. I would also like to avoid allocating a new vector every time this function is called.
But how I can I get the desired behaviour? When the the components are added I can create an std::vector of the desired derived type.
The question could also be: How can I have an std::map containing different types of std::vector?
For any solutions I can not link against boost, though if absolutely needed, I could integrate single headers of boost.
template<class It>
struct range_view {
It b, e;
It begin() const { return b; }
It end() const { return e; }
using reference = decltype(*std::declval<It const&>());
reference operator[](std::size_t n) const
{
return b[n];
}
bool empty() const { return begin()==end(); }
std::size_t size() const { return end()-begin(); }
reference front() const {
return *begin();
}
reference back() const {
return *std::prev(end());
}
template<class O>
range_view( O&& o ):
b(std::begin(o)), e(std::end(o))
{}
};
this is a quick range view. It can be improved.
Now all you need to do is write a pseudo-random-access iterator that converts its arguments. So it takes a random access iterator over a type T, then does some operation F to return a type U. It forwards all other operations.
The map then stores std::vector<std::shared_ptr<Base>>. The gettor returns a range_view< converting_iterator<spBase2spDerived> >.
Here is a crude implementation of a solution I have in mind for this problem. Of course, there are many rooms to refine the code, but hopefully it conveys my idea.
#include <iostream>
#include <map>
#include <vector>
#include <memory>
using namespace std;
class Base {
public:
virtual void f() const = 0;
};
class A : public Base {
public:
static const int type = 0;
explicit A(int a) : a_(a) {}
void f() const { cout << "calling A::f" << endl;}
int a_;
};
class B : public Base {
public:
static const int type = 1;
explicit B(int a) : a_(a) {}
void f() const { cout << "calling B::f" << endl;}
int a_;
};
class MapWrapper {
public:
template<class T>
void append(int a, vector<T> const& vec) {
types_[a] = T::type;
my_map_[a] = make_shared<vector<T>>(vec);
}
template<class T>
vector<T> const& get(int a) const {
return *static_pointer_cast<vector<T>>( my_map_.at(a) );
}
map<int, shared_ptr<void>> const& get_my_map() const {
return my_map_;
}
vector<shared_ptr<Base>> get_base(int a) const {
vector<shared_ptr<Base>> ret;
switch(types_.at(a)) {
case 0: {
auto const vec = get<A>(a);
for(auto v : vec)
ret.push_back(make_shared<A>(v));
break;
}
case 1: {
auto const vec = get<B>(a);
for(auto v : vec)
ret.push_back(make_shared<B>(v));
break;
}
}
return ret;
}
map<int, shared_ptr<void>> my_map_;
map<int, int> types_;
};
int main() {
MapWrapper map_wrapper;
map_wrapper.append(10, vector<A>{A(2), A(4)});
map_wrapper.append(20, vector<B>{B(5), B(7), B(9)});
for(auto const& w : map_wrapper.get_my_map())
for(auto v : map_wrapper.get_base(w.first))
v->f();
for(auto const& x: map_wrapper.get<A>(10))
cout << x.a_ << " ";
cout << endl;
for(auto const& x: map_wrapper.get<B>(20))
cout << x.a_ << " ";
return 0;
}
The solution was to use reinterpret_cast:
template<class T> inline std::vector<std::shared_ptr<T>> * getVector() const
{
auto key = getKey<T>();
return reinterpret_cast<std::vector<std::shared_ptr<T>> *>( (_componentMap.count(key) ? _componentMap.at(key).get() : const_cast<std::vector<std::shared_ptr<Component>> *>(&_emptyComponentSharedPtrVec)) );
}
It's not very pretty but it does work fine and it fulfills all requirements.

Using class member variables that hold functions in definition of inner structures that will be used as template arguments of an unordered_map object

I am implementing an object that makes use of unordered_map. The object is to be generic, so templates everywhere. In particular the operator== and operator() are wrapped into structures that are used by the unordered_map to respectively check if keys are equal and to generate hash values for keys. I'd like the user to write their own functions that implement the above two operators and pass those methods as input to the class object. The structs would then use those objects. I'm having some trouble with scopes and can't seem to figure out how to do it. Here's my code:
#include <unordered_map>
#include <iostream>
#include <string>
#include <functional>
template <typename O>
class aClass
{
public:
aClass( bool (usrIsEq)(O, O) ,
std::size_t (usrHashFtn)(O) )
{
this->usrIsEq = usrIsEq;
this->usrHashFtn = usrHashFtn;
}
void add(O k, std::string v)
{
iTable[ {k} ] = v;
}
std::string get(O k)
{
return iTable[ {k} ];
}
private:
bool (*usrIsEq)(O, O);
std::size_t (*usrHashFtn)(O);
struct Key
{
O obj;
bool operator==(const Key &other) const
{
std::cout << "obj " << obj << std::endl;
return usrIsEq(obj, other.obj);
}
};
struct KeyHasher
{
std::size_t operator()(const Key &k) const
{
return usrHashFtn(k);
}
};
std::unordered_map<Key, std::string, KeyHasher> iTable;
};
bool isEqInts(int a, int b)
{
return a == b;
}
std::size_t intHashFtn(int x)
{
std::hash<int> hf;
return hf(x);
}
int main()
{
aClass<int> x(isEqInts, intHashFtn);
x.add( 1, std::string("hello") );
}
I'm not entirely sure how to implement the structs Key and KeyHasher so that they use the functions contained inside the class. The only thing I truly care about is that the functions are given as input to the class constructor. Everything else can be scrapped.
The main problem that's tripping you up is that Key has no knowledge usrIsEq and KeyHasher has no knowledge of usrHashFtn. You need to pass a pointer or reference to an object of aClass to those classes.
Here' one suggestion:
struct Key
{
O obj;
aClass* ac;
bool operator==(const Key &other) const
{
std::cout << "obj " << obj << std::endl;
return ac->usrIsEq(obj, other.obj);
}
};
struct KeyHasher
{
std::size_t operator()(const Key &k) const
{
return k.ac->usrHashFtn(k.obj);
}
};
and update the places where you use Key to access the table:
void add(O k, std::string v)
{
iTable[{k, this}] = v;
}
std::string get(O k)
{
return iTable[{k, this}];
}

Emulate std::map iterators for custom map that does not use tuples

I want to create a custom map that that actually uses a fixed set of keys, but should behave like a std::map. Basically I use an array internally and map the keys to indexes, allowing very efficient lookup. I am however struggling to implement iterators that behave like std::map iterators, because I do not have internal std::pairs that I can hand out references to.
Is it possible to implement this as a zero-overhead abstraction while retaining the std::map interface, in particular the iterators?
The best i could come up with as operator* is to return a rvalue std::pair<key_type, mapped_type*>, which basically allows for the same operations, but unfortunately with different usage patterns.
I have also tried std::pair<key_type, boost::referene_wrapper<mapped_type>>, but that still doesn't allow for(auto& elem : map) and often requires elem.second.get() for reasons I do not understand.
I am happy to use boost or lightweight header libraries, if there is anything that helps for the use case.
To illustrate the case, here is a minimal example with a map that contains all letters 'a'-'z'.
using letter = char;
static const letter letter_begin = 'a';
static const letter letter_end = 'z' + 1;
template <typename T>
class letter_map
{
private:
using self = letter_map<T>;
template <typename IT, typename M>
class iterator_base : public std::iterator<std::input_iterator_tag, T>
{
public:
iterator_base(letter index, M& map) : index_(index), data_(map)
{
}
using self_iter = iterator_base<IT, M>;
IT operator*()
{
return IT(index_, &data_[index_]);
}
self_iter& operator++()
{
index_++;
return *this;
}
self_iter operator++(int)
{
self_iter tmp(*this);
operator++();
return tmp;
}
bool operator==(self_iter other) const
{
assert(&data_ == &other.data_);
return index_ == other.index_;
}
bool operator!=(self_iter other) const
{
return !(*this == other);
}
private:
letter index_;
M& data_;
};
public:
using key_type = letter;
using mapped_type = T;
using value_type = std::pair<const key_type, mapped_type*>;
using const_value_type = std::pair<const key_type, const mapped_type*>;
private:
static const size_t data_size = letter_end - letter_begin;
using container_type = std::array<mapped_type, data_size>;
public:
using iterator = iterator_base<value_type, self>;
using const_iterator = iterator_base<const_value_type, const self>;
public:
mapped_type& operator[](letter l)
{
return data_[l - letter_begin];
}
const mapped_type& operator[](letter l) const
{
return data_[l - letter_begin];
}
auto begin()
{
return iterator(letter_begin, *this);
}
auto end()
{
return iterator(letter_end, *this);
}
auto begin() const
{
return const_iterator(letter_begin, *this);
}
auto end() const
{
return const_iterator(letter_end, *this);
}
private:
container_type data_;
};
void print_string_letter_map(const letter_map<std::string>& lm)
{
for (auto elem : lm)
{
std::cout << elem.first << "->" << *(elem.second) << std::endl;
}
}
template<typename T>
class std_letter_map : public std::map<letter, T>
{
public:
std_letter_map()
{
for (letter l = letter_begin; l != letter_end; ++l) {
this->emplace(l, T());
}
}
};
void print_string_std_letter_map(const std_letter_map<std::string>& lm)
{
for (const auto& elem : lm)
{
std::cout << elem.first << "->" << elem.second << std::endl;
}
}
int main()
{
letter_map<std::string> lm;
// usually I would use auto& elem here
for (auto elem : lm) {
auto let = elem.first;
// usually this would be without the *
auto& str = *(elem.second);
str = std::string("foo ") + let;
}
print_string_letter_map(lm);
return 0;
}
Implementing operator * is easy - just return std::pair<const Key, Value&> or ..., Value const&> for const iterator, like in this simplified example:
template <typename T>
class iterator_array_as_map
{
public:
iterator_array_as_map(T* array, int index)
: array(array), index(index)
{}
bool operator == (const iterator_array_as_map& other) const
{
return index == other.index;
}
bool operator != (const iterator_array_as_map& other) const
{
return index != other.index;
}
iterator_array_as_map& operator ++ ()
{
++index;
return *this;
}
auto operator * ()
{
return std::pair<const int, T&>(index, array[index]);
}
private:
T* array;
int index;
};
And usage:
int main() {
int array[2] = {2, 4};
auto begin = iterator_array_as_map<int>(array, 0);
auto end = iterator_array_as_map<int>(array, 2);
for (auto it = begin; it != end; ++it)
{
std::cout << (*it).first << " " << (*it).second << std::endl;
}
(*begin).second = 7;
for (auto it = begin; it != end; ++it)
{
std::cout << (*it).first << " " << (*it).second << std::endl;
}
}
operator -> is a little harder - since you must return something which needs to emulate pointer to std::pair - but if do not mind about dynamic memory fragmentation - you can just return std::shared_ptr<std::pair<....>>...
auto operator -> ()
{
return std::make_shared<std::pair<const int, T&>>(index, array[index]);
}
If you do not want to use dynamic memory - then you might try with pointer to itself solution:
template<typename data>
class pointer_to_data
{
public:
template<typename ...Arg>
pointer_to_data(Arg&&... arg)
: data{std::forward<Arg>(arg)...}
{}
Data* operator -> ()
{
return &data;
}
private:
Data data;
};
Just return the above instead shared_ptr...
See this what-is-the-correct-way-of-using-c11s-range-based-for, section "The special case of proxy iterators". It is not possible to define for(auto&e:b) if b is e.g. std::vector<bool>- because in general it is not possible to have reference to temporary, and this very container is similar to yours in this sense that it has "Special" reference type.
You can try to have special member in your iterator keeping the "return value"- but that would be troublesome - so probably no better that this presented by me solution exist.
You could probably use zip_view from Eric Niebler's range library
https://github.com/ericniebler/range-v3

Object with attributes of any type with easy storage and iteration

I have an "object" with different attributes stored as key/value. The key is a string and the value can be any basic type. My first idea was using a template class:
template <class T>
class Attribute {
public:
Attribute<T>(const std::string& key, T value) :
m_key(key),
m_value(value)
{
}
~Attribute(){}
T getValue() const
{
return m_value;
}
std::string getKey() const
{
return m_key;
}
private:
std::string m_key;
T m_value;
};
But now the problem is that in my object class, I have to declare fields and overload functions for each possible attribute type:
class MyObject {
public:
MyObject(int value) :
m_value(value)
{
}
~MyObject()
{
}
int getValue() const
{
return m_value;
}
void addAttribute(Attribute<int> attribute)
{
m_intAttributes.push_back(attribute);
}
void addAttribute(Attribute<double> attribute)
{
m_doubleAttributes.push_back(attribute);
}
const std::list<Attribute<int> >& getIntAttributes() const
{
return m_intAttributes;
}
const std::list<Attribute<double> >& getDoubleAttributes() const
{
return m_doubleAttributes;
}
private:
int m_value;
std::list<Attribute<int> > m_intAttributes;
std::list<Attribute<double> > m_doubleAttributes;
};
Moreover, iterating through the attributes is not very comfortable and looking for an attribute of a given name is very difficult:
void showMyObject(const MyObject& myObject)
{
std::list<Attribute<int> > intAttributes;
std::list<Attribute<int> >::const_iterator itInt;
std::list<Attribute<double> > doubleAttributes;
std::list<Attribute<double> >::const_iterator itDouble;
std::cout << "Value in myObject " << myObject.getValue() << std::endl;
intAttributes = myObject.getIntAttributes();
for(itInt = intAttributes.begin() ; itInt != intAttributes.end() ; itInt++)
{
std::cout << itInt->getKey() << " = " << itInt->getValue() << std::endl;
}
doubleAttributes = myObject.getDoubleAttributes();
for(itDouble = doubleAttributes.begin() ; itDouble != doubleAttributes.end() ; itDouble++)
{
std::cout << itDouble->getKey() << " = " << itDouble->getValue() << std::endl;
}
}
FYI, my main function looks like this:
int main(int argc, char* argv[])
{
MyObject object(123);
object.addAttribute(Attribute<double>("testDouble", 3.23));
object.addAttribute(Attribute<double>("testDouble2", 99.654));
object.addAttribute(Attribute<int>("testInt", 3));
object.addAttribute(Attribute<int>("testInt2", 99));
showMyObject(object);
return 0;
}
I guess if we want to guarantee type safety, there must be somewhere list of functions with the right return type in the signature (getTYPEAttributes in my example).
However, I was wondering if a more elegant solution exists and if a design pattern I'm not aware of could help me to handle this problem correctly.
Sounds like a job for Boost.TypeErasure. You want to store different kinds of things that share common traits (are streamable, have a key), but can be explicitly accessed and don't need a common base? Store your attributes thusly:
namespace mpl = boost::mpl
using namespace boost::type_erasure;
BOOST_TYPE_ERASURE_MEMBER((has_getKey), getKey, 0)
using AnyAttribute = any<mpl::vector<
copy_constructible<>,
typeid_<>,
ostreamable<>, // add a stream operator for Attribute
has_getKey<std::string(), const _self>
> >;
std::vector<AnyAttribute> attributes;
Adding an attribute would look like:
template <typename T>
void addAttribute(const std::string& key, const T& value) {
// since Attribute<T> is copy-constructible, streamable,
// and has a member function with the signature std::string getKey() const
// we can construct an AnyAttribute with it.
attributes.push_back(Attribute<T>(key, value));
}
Printing all of the attributes:
void showMe() {
for (const auto& attr : attributes) {
std::cout << attr << ' '; // since we specified ostreamable<>,
// everything we put into this any<> is streamable
// so the any<> is too
}
std::cout << '\n';
}
Looking up an attribute by name and specified type, returns nullptr if not found or wrong type:
template <typename T>
const Attribute<T>* lookupAttribute(const std::string& key) {
// can use getKey() even if they're all different types
// because we added has_getKey<> as a concept
auto it = std::find_if(attributes.begin(), attributes.end(),
[=](const AnyAttribute& a) {
return a.getKey() == key;
});
if (it != attributes.end()) {
// this will return a valid Attribute<T>* you specified the
// correct type, nullptr if you specified the incorrect type
// it is not possible to query the type.
return any_cast<Attribute<T>*>(&*it);
}
else {
return nullptr;
}
}
There's a simpler type-erased object which is just Boost.Any, but there you cannot have any kind of common functionality - which would make it difficult to implement either the lookup or the printing operations I illustrated above.