Overload custom comparator to std::map - c++

I am trying to solve this problem. I came up with this solution:
typedef unordered_map<string, double> stockDictType;
class StockTicker {
class Comparator {
public:
inline bool operator() (const string &a, const string &b) const {
return stocksDict.at(a) < stocksDict.at(b);
}
};
stockDictType stocksDict;
map<string, stockDictType::iterator, Comparator> stocksTicker; // this is where I need a custom comparator method
int tickerSize;
public:
StockTicker(int k): tickerSize(k) {}
// some other methods
};
As is evident, this fails to compile: StockTicker::stocksDict is not a static member. Now I can't make it so because I could require multiple instances of the StockTicker class.
std::map uses a strict comparator function parameter definition (std::map will only pass in the keys to be compared), so I can't overload it to pass a reference to the current instance of the StockTicker class (which I could've used to get access to StockTicker::stocksDict through public getters)
I took inspiration from this SO question and the subsequent answer to do this:
typedef unordered_map<string, double> stockDictType;
class StockTicker {
class Comparator {
public:
stockDictType &_stockDictRef;
explicit Comparator(stockDictType &stocksDict): _stockDictRef(stocksDict) {}
inline bool operator() (const string &a, const string &b) const {
return _stockDictRef.at(a) < _stockDictRef.at(b);
}
};
stockDictType stocksDict;
map<string, stockDictType::iterator, Comparator> stocksTicker(Comparator{stocksDict});
int tickerSize;
public:
StockTicker(int k): tickerSize(k) {}
void addOrUpdate(string name, double price) {
stocksDict[name] = price;
stocksTicker.at(name) = stocksDict.find(name);
}
vector<stockDictType::iterator> top() {
vector<stockDictType::iterator> ret(tickerSize);
auto it = stocksTicker.begin();
for(int i = 0; i < tickerSize; i++, it++)
ret[i] = it->second;
return ret;
}
};
This won't compile either. I get this kind of error in the StockTicker::addOrUpdate() and StockTicker::top() methods:
error: '((StockTicker*)this)->StockTicker::stocksTicker' does not have class type.
I tried a bunch of other stuff too (like declaring a public comparator method in the StockTicker class itself and trying to pass a function pointer of it to std::map. That failed as well; StockTicker::stocksTicker gets declared before the comparator method does and the compiler complains).
Any ideas on how to go about fixing this?

std::map<std::string, stockDictType::iterator, Comparator> stocksTicker(Comparator(stocksDict));
this defines a member function named stocksTicker that takes a stocksDict argument of type Comparator and returns a std::map.
std::map<std::string, stockDictType::iterator, Comparator> stocksTicker{Comparator{stocksDict}};
This defines a member variable stocksTicker which, by default, is initialized with a Comparator, which in turn was initialized with the member variable stocksDict.
I assume you want the second.
Your syntax was partway between the two. Whatever compiler you had got confused by this.
Live example
You should StockTicker(StockTicker &&)=delete and StockTicker& operator=(StockTicker &&)=delete, as maps containing references to their containing class are not safe to move or copy.
Generating an efficient move here is tricky. I suspect C++17 node splicing might make it possible to do it. You might have to embed a std::shared_ptr<stocksDict*> (yes, a shared pointer to a pointer), and use .key_comp to reseat the stocksDict in the target.

Related

C++ type punning with classes

I am writing some C++ code which wraps the std::unordered_map type, where I want to hide the underlying type and present it as another type. More specifically, I want to wrap the std::pair from the std::unordered_map with another type. For the sake of argument, lets suppose the wrapper looks like this...
template <typename ActualT >
class wrapper final
{
private:
ActualT actual_;
public:
//Some constructors...
typename ActualT::first_type & get_first()
{
return actual_.first;
}
typename ActualT::second_type & get_second()
{
return actual_.second;
}
};
My reasoning is that since the wrapper class only has a member which is the exact type which it is wrapping, converting a reference from the original type to the wrapper type should be fine, but the type compatibility for structs states that the members should have the same type and name for the types to be compatible. Would using type-punning in this fashion potentially cause undefined behaviour or alignment issues?
using my_map = std::unordered_map < int, int >;
my_map m;
//Do some inserts...
reinterpret_cast<wrapper<typename my_map::value_type>&>(*m.find(10)).get_second() = 1.0;
I want client code to be allowed to access the entries of a map without knowing about the pair which is returned by the map. I also want to write a custom forward iterator, hence I need to return a reference to the entry. Would converting the reference to the pair to a reference to a class which act as a wrapper be considered dangerous?
Is there perhaps a better approach to accomplishing this?
This absolutely is undefined behaviour.
Seriously rethink your priorities.
Some free functions of the form
const my_map::key_type & MeaningfulNameHere(my_map::reference)
will go a long way to giving you meaningful names.
If you must wrap the standard library with different names, just use a non-explicit constructor, and store references.
template <typename Map>
class entry final
{
private:
typename Map::reference ref;
public:
entry(Map::reference ref) : ref(ref) {}
const typename Map::key_type & key()
{
return ref.first;
}
typename Map::mapped_type & value()
{
return ref.second;
}
};
If you really need the iterator to dereference to entry you can. But you can just implicitly instantiate entrys from the Map::references returned by Map::iterator::operator*, you don't need a custom iterator.
template <typename Map>
class entry_iterator
{
private:
typename Map::iterator it;
entry<Map> entry;
public:
entry<Map>& operator*() { return entry; }
entry_iterator operator++() { ++it; entry = *it; return *this; }
// etc
}
So you could clean this up, but I wouldn't suggest it:
#include <unordered_map>
#include <iostream>
using namespace std;
template <class Key, class Value>
class wrapper
{
public:
explicit wrapper(std::pair<const Key, Value>& kvp)
: _key{kvp.first}
, _value{kvp.second}
{}
const Key& key() const { return _key; }
Value& value() { return _value; }
private:
const Key& _key;
Value& _value;
};
int main()
{
unordered_map<int,int> m;
m[1] = 1;
m[3] = 3;
auto it = m.find(1);
wrapper w{*it};
w.value() = 30;
std::cout << w.key() << " -> " << w.value() << '\n';
}
The above effectively hides the pair from users of your class. It doesn't deal with exceptions (find() returning end() for example), and makes no guarantees about lifetimes. It's marginally better than what you have because it doesn't require a reinterpret_cast to an unrelated type.
However, map, unordered_map, set, etc. storing returning iterators as pairs is just part of library -- it's the canonical form and I don't see the benefit of shielding people from it.

Can I define implicit conversion from std::function to std::shared_ptr<MyClass>?

I have a class that works as a predicate to select value from list.
class Predicate {
public:
// In this example, I am using QString as value type
// this is not what happens in actual code, where more complex data is being validated
virtual bool evaluate(const QString& val) const = 0;
};
Originally, I used lambda functions but this created lot of repetitive garbage code. So instead, I want to use predicate classes that use inheritance. For example:
class PredicateMaxLength: public RowPredicate {
public:
PredicateMaxLength(const int max) : maxLength(max) {}
virtual bool evaluate(const QString& val) const {return val.length()<maxLength;}
protected:
const int maxLength;
};
To allow inheritance do it's deed, pointers are given rather than values:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(const std::shared_ptr<Predicate> pred);
}
Now we are surely stil going to use lambdas in cases where code would not be repetitive (eg. some special case). For this purpose, PredicateLambda has been created:
typedef std::function<bool(const QString& val)> StdPredicateLambda;
class PredicateLambda: public Predicate {
public:
PredicateLambda(const StdPredicateLambda& lambda) : RowPredicate(), callback_(lambda) {}
virtual bool evaluate(const QString& val) const override {return callback_(val);}
protected:
const StdPredicateLambda callback_;
};
The nasty effect of this is that whenever lambda is used, it must be wrapped into PredicateLambda constructor:
myObject.deleteItems(std::make_shared<PredicateLambda>([]->bool{ ... lambda code ... }));
This is ugly. I have two options:
for every function that accepts predicate, have an overload that does the conversion seen above. This duplicates number of methods in header file
Have an implicit conversion from std::function<bool(const QString& val)> to std::shared_ptr<Predicate> which would execute this:
std::shared_ptr<Predicate> magicImplicitConversion(const StdPredicateLambda& lambdaFn) {
return std::make_shared<PredicateLambda>(lambdaFn);
}
I came here to ask whether the second option is possible. If it is, does it carry any risk?
If you don't want to use template to not expose code, you may use std::function:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(std::function<bool(const QString&)> pred);
};
and your predicate
class PredicateMaxLength {
public:
explicit PredicateMaxLength(int max) : maxLength(max) {}
bool operator ()(const QString& val) const {return val.length()<maxLength;}
protected:
int maxLength;
};
So you can use either
SomeDataObject someDataObject;
someDataObject.removeValues(PredicateMaxLength(42));
someDataObject.removeValues([](const QString& s) { return s.size() < 42; });
You want polymorphism, and you don't want to use template-style header lambdas. And you want to be able to have a few default cases.
The right answer is to throw out your Predicate class.
Use using Predicate = std::function<bool(const QString&)>;.
Next, note that your Predicate sub-types are basically factories (the constructor is a factory) for Predicates with some extra state.
For a std::function, such a factory is just a function returning a Predicate.
using Predicate = std::function<bool(const QString&)>;
Predicate PredicateMaxLength(int max) {
return [max](QString const& str){ return val.length()<max; }
}
where the body of PredicateMaxLength goes in a cpp file.
If you have an insanely complicated set of state for your Predicate-derived class, simply give it an operator() and store it within a std::function. (In the extremely rare case that you have some state you should store in a shared ptr, just store it in a shared ptr).
A std::function<Signature> is a regular type that is polymorphic. It uses a technique known as type erasure to be both a value and polymorphic, but really you can call it magic.
It is the right type to use when you are passing around an object whose only job is to be invoked with some set of arguments and return some value.
To directly answer your question, no, you cannot define a conversion operator between a std::function and a std::shared_ptr<yourtype> without making your program ill formed, no diagnostic required.
Even if you could, a std::function is not a lambda, and a lambda is not a std::function. So your conversion operator wouldn't work.

How do I pass a variable to a function object?

In the examlpe below I need to define a function to compare my objects using certain rules in getHappiness(Animal*) method. The method cannot be static and rather complicated. I need a pointer in the comparison definition to call getHappiness method.
So my question is: how do I pass a pointer to this method, it gets called automatically when I insert an element into the map. And also it doesn't seem that I can instantiate Compare structure and pass the pointer to the constructor.
Am I doing anything wrong? Maybe there is an alternative way to how I define a comparison function?
struct Compare {bool operator()(Animal* const, Animal* const) const;};
bool
Compare::operator()(Animal* const a1, Animal* const a2) const {
Zoo* zoo; // somehow I need to get access to the Zoo instance here
if (zoo->getHappiness(a1) > zoo->getHappiness(a2)) return true;
return false;
}
Class Zoo(){
std::multimap<Animal*, Man*, Compare> map;
int getHappiness(Animal*); // cannot be static
}
int main(){
...
Zoo zoo;
zoo.map.insert(...);
...
}
There is a design issue in your code. Happiness should be an attribute which belong to an animal not a zoo. So implement getHappiness() on animal makes your code much simpler:
struct Compare
{
bool operator()(Animal& const, Animal& const) const;
};
bool Compare::operator()(Animal& const a1, Animal& const a2) const
{
return a1.getHappiness() < a2.getHappiness();
}
Class Zoo(){
std::multimap<Animal, Man, Compare> map;
}
Also, if not necessary, don't use pointer. If you can't avoid pointer, use smart pointer in STL container.

Comparison function for C++ STL set: Can comparison function be a member function of a class?

I have to use STL set and I want to define my own comparison function. But as per my requirement this comparison function shouldn't be a global, rather should be a public member of a class.
//CLASS DEFINITION
class IDENTIFERS
{
public:
IDENTIFIERS();
~IDENTIFIERS();
bool compare_identifier(int Identifier, int Identifier);
public:
std::set <Identifier, bool(*)(Identifier, Identifier)> set_instance;
};
//CLASS Constructor
IDENTIFIERS::IDENTIFIERS()
{
std::set <Identifier, bool(*)(Identifier, Identifier)> set_instance(compare_identifier);
}
If I write a piece a code as mentioned above. It doesn't compile as comparison function's prototype doesn't match with compare_identifier() function.
Is there a way to do it?
A non-static member function takes an implicit first parameter for this, so your compare_identifier actually has three parameters. If you need it to be a non-static member function, you need to bind the member function's implicit first parameter to an instance of IDENTIFIERS, for example,
#include <set>
#include <functional>
struct Identifier { int id; };
class IDENTIFERS
{
public:
IDENTIFERS() : set_instance(std::bind(&IDENTIFERS::compare_identifier,
this,
std::placeholders::_1,
std::placeholders::_2))
{}
bool compare_identifier(const Identifier& lhs, const Identifier& rhs)
{
return lhs.id < rhs.id;
}
public:
std::set <Identifier, std::function<bool(const Identifier&, const Identifier&)>> set_instance;
};
There are a number of errors in your sample code.
The zero-th error is somewhat style-related: classes should be named all-lowercase-with-underscores or CamelCase.
The first error:
bool compare_identifier(int Identifier, int Identifier);
you can't have the same identifier for both function parameters (also, style-related, function parameters should be all-lowercase or camelCased), like
bool compare_identifier(int id1, int id2);
The second error is that this:
std::set <Identifier, bool(*)(Identifier, Identifier)> set_instance;
assumes that you have a class Identifier somewhere. Which something tells me you don't, since your class is called IDENTIFIERS. If you do have an Identifier class, I should assume that your compare_identifier function is like:
bool compare_identifier(const Identifier& id1, const Identifier& id2);
and that your set_instance declaration is like:
std::set<Identifier, bool(*)(const Identifier&, const Identifier&)> set_instance;
The third error is that your constructor does not do what you are assuming it does (constructing the set_instance member), but it would be (if syntatically valid) constructing a local variable called set_instance. So, your constructor should go something like:
IdentifierBucket::IdentifierBucket() :
set_instance(std::bind(compare_identifier, this, _1, _2)) {
}
But all this is moot... because the comparator for set also does not do what you think it does (see if two items are equal or not) but it gives them order (the default comparator is std::less...
What you really want is something like:
#include <set>
#include <functional>
struct Identifier {};
struct IdentifierComparator {
IdentifierComparator() {};
bool operator()(Identifier id1, Identifier id2); // WRITE THIS
};
class IdentifierBucket {
public:
IdentifierBucket() {};
~IdentifierBucket() {};
private:
std::set <Identifier, IdentifierComparator> set_instance;
};
Making compare_identifier() static is the easiest way to solve this. Here is how you can fix your code so that it compiles, assuming Identifier is defined elsewhere:
// Watch for the typo (missing 'I') in your code above
class IDENTIFIERS // Note, all-uppercase names are usually reserved for macros
{
public:
IDENTIFIERS();
// N.B: This function needs to take two `Identifier`s as its arguments
// (not two `int`s)
static bool compare_identifier(Identifier const &l, Identifier const& r)
{
return l.custom_less_than(r);
}
// typedefs can make your code more readable, especially with function pointers.
typedef bool (*identifier_comparator)(Identifier const &l, Identifier const& r);
typedef std::set<Identifier, identifier_comparator> identifier_set;
identifier_set set_instance;
};
IDENTIFIERS::IDENTIFIERS()
:set_instance(compare_identifier) // Initialise here
{
// Don't shadow `set_instance` in the body of the constructor!
}
Following comment
Making compare_identifier() static (in IDENTIFIERS) will not affect the accessibility of members of the Identifier class. The logic to compare two Identifier objects should reside either within Identifier, like this:
class Identifier
{
public:
// If you define this, then you won't need to specify a custom comparator
bool operator <(Identifier const& r) const
{
// return true if `*this` is logically less-than `r`; false otherwise.
}
bool custom_less_than(Identifier const& r) const
{
// Some other way of comparing objects. Perhaps reverse-alphabetically
// or similar.
// return true if `*this` is logically less-than `r`; false otherwise.
}
};
...or within free functions but these won't have access to the private members.

Generic container for multiple data types in C++

Using C++, I'm trying to create a generic container class to handle multiple data types. It's a common problem with a variety of solutions, but I've found nothing as... intuitive as I've grown accustomed to in languages like Python or even VB/VBA...
So here's my scenario:
I've built a DataContainer class based on boost::any which I use to store multiple data types of multiple elements. I use a map declared as:
std::map<std::string, DataContainer* (or DataContainerBase*)>
where DataContainer is a class that encapsulates an object of the type:
std::list<boost::any>
along with convenience functions for managing / accessing the list.
However, in the end, I'm still forced to do type conversions outside the data container.
For example, if I were to store a list of int values in the map, accessing them would require:
int value = boost::any_cast<int>(map["myValue"]->get());
I'd rather the boost code be contained entirely within the data container structure, so I would only need type:
int value = map["myValue"]->get();
or, worst-case:
int value = map["myValue"]->get<int>();
Of course, I could enumerate my data types and do something like:
int value = map["myValue"]->get( TYPE_INT );
or write type-specific get() functions:
getInt(), getString(), getBool() ...
The problem with the last two options is that they are somewhat inflexible, requiring me to declare explicitly each type I wish to store in the container. The any_cast solution (which I have implemented and works) I suppose is fine, it's just... inelegant? I dunno. It seems I shouldn't need to employ the internal mechanics externally as well.
As I see it, passing the value without declaring the value type in the call to the DataContainer member function would require a void* solution (which is undesirable for obvious reasons), and using a "get()" call would require (so far as I can tell) a "virtual template" member function defined at the base class level, which, of course, isn't allowed.
As it is, I have a workable solution, and really, my use in this case is limited enough in scope that most any solutions will work well. But I am wondering if perhaps there's a more flexible way to manage a generic, multi-type data container than this.
If you want to introduce some sugar for this:
int value = boost::any_cast<int>(map["myValue"]->get());
then you might want to make the get() function to return a proxy object, defined +- like this:
struct Proxy {
boost::any& value;
Proxy(boost::any& value) : value(value) {}
template<typename T>
operator T() {
return boost::any_cast<T>(value);
}
};
Then this syntax would work:
int value = map["myValue"]->get();
// returns a proxy which gets converted by any_cast<int>
However I recommend to keep things explicit and just use that syntax:
int value = map["myValue"]->get<int>();
Here get doesn't return a proxy object with a template method, but is a template method itself (but does the same as the template conversion operator shown above).
Today I have done some source code for the purpose you want. I know that this question is so old, but maybe this little piece of code is helpful for someone. It is mainly based on boost:any.
/*
* AnyValueMap.hpp
*
* Created on: Jun 3, 2013
* Author: alvaro
*/
#ifndef ANYVALUEMAP_HPP_
#define ANYVALUEMAP_HPP_
#include <map>
#include <boost/any.hpp>
using namespace std;
template <class T>
class AnyValueMap {
public:
AnyValueMap(){}
virtual ~AnyValueMap(){}
private:
map<T, boost::any> container_;
typedef typename map<T, boost::any>::iterator map_iterator;
typedef typename map<T, boost::any>::const_iterator map_const_iterator;
public:
bool containsKey(const T key) const
{
return container_.find(key) != container_.end();
}
bool remove(const T key)
{
map_iterator it = container_.find(key);
if(it != container_.end())
{
container_.erase(it);
return true;
}
return false;
}
template <class V>
V getValue(const T key, const V defaultValue) const
{
map_const_iterator it = container_.find(key);
if(it != container_.end())
{
return boost::any_cast<V>(it->second);
}
return defaultValue;
}
template <class V>
V getValue(const T key) const
{
return boost::any_cast<V>(container_.at(key));
}
template <class V>
void setValue(const T key, const V value)
{
container_[key] = value;
}
};
#endif /* ANYVALUEMAP_HPP_ */
A simple usage example:
AnyValueMap<unsigned long> myMap;
myMap.setValue<double>(365, 1254.33);
myMap.setValue<int>(366, 55);
double storedDoubleValue = myMap.getValue<double>(365);
int storedIntValue = myMap.getValue<int>(366);