I have vector of objects and a vector of criteria to filter by. Inspired by Moo-Juice from this post, I wrote such a code:
#include <algorithm>
#include <string>
#include <memory>
#include <vector>
struct Token {
char code;
int val;
Token(char c,int a) : code(c),val(a) {}
};
class FilterBase {
public:
virtual bool operator()(const std::shared_ptr<Token> p) =0;
};
class ByCode : public FilterBase {
public:
ByCode( char c) : code_(c) {}
virtual bool operator()(const std::shared_ptr<Token> p) {
return code_ == p->code;
}
private:
unsigned char code_;
};
int main() {
std::vector<std::shared_ptr<FilterBase>> filters;
filters.push_back(std::make_shared<ByCode>('A'));
filters.push_back(std::make_shared<ByCode>('B'));
std::shared_ptr<Token> p = std::make_shared<Token>('M', 20);
std::vector<std::shared_ptr<Token>> tokens;
tokens.push_back(p);
filters[0]->operator ()(p);
for (const std::shared_ptr<FilterBase> fi : filters) {
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), *fi), tokens.end());
}
}
But unfortunately it does not compile, because parameter type 'FilterBase' is an abstract class. Well I know it is, I just thoght the virtual keyword would make it working...
Replace:
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), *fi), tokens.end());
with:
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), std::ref(*fi)), tokens.end());
remove_if takes its functor by-value, which causes your *fi to be sliced into an instance of the base class, which has a pure virtual object. Things go poorly.
std::ref has an overloaded operator() which should invoke the virtual operator() of *fi if MSVC didn't screw things up (for example, if it invokes the operator the wrong way).
If this fails, you can write your own adapter:
template<typename T>
struct callable_by_ref {
T* t;
template<typename... Args>
auto operator(Args&&...args) const ->
decltype( std::declval<T&>()(std::declval<Args&&>()...) )
{
return (*t)(std::forward<Args>(args)...);
}
};
template<typename T>
callable_by_ref< typename std::remove_reference<T>::type >
call_by_ref( T&& t ) {
return {&t};
}
which should solve your problem even if std::ref does not.
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), call_by_ref(*fi)), tokens.end());
What I am doing:
The callable_by_ref is basically a quick perfect forwarder with a half-functional std::reference_wrapper implementation on top of it. call_by_ref does type deduction for you to create such an object.
Related
Is it possible to get rid of the template in the following code?
The idea is to use a std::priority_queue with classes honouring the Compare concept via an home-made abstract class.
Some of the problems I faced are:
The priority queue wont init with an abstract Compare.
there is no default constructors for classes inheriting from Compare, because they all have specific parameters.
an Algorithm is responsible for initializing the data structure used by the Compare instances.
EDIT: there may exists several implementations of Algorithm, using different data structures needing a Compare, and the user of the class should be able to decide which Compare he want to use.
I dislike the design given hereafter because people implementing Algorithm are not really forced to call Compare::attach and the Compare class should thus have a state management (not shown here).
It also force the user to indicate a compare template AND pass the corresponding instance (because the compiler cannot infer it in the constructor of an Algorithm). This is mitigated by the make_algo function, but I would rather avoid this exotic construction (not that exotic, but still).
Is there a design in which I can use the Compare abstract class in an Algorithm instead of a template?
#include <vector>
#include <queue>
class Compare
{
private:
std::vector<int>* _costs;
protected:
std::vector<int>& costs() {return *_costs;}
int cost(const int i) const {return (*_costs)[i];}
public:
Compare() : _costs(nullptr) {}
void attach(std::vector<int> & costs_) {_costs = &costs_;}
virtual bool operator()( const int a, const int b ) const = 0;
};
struct CompCosts : public Compare
{
virtual bool operator()( const int a, const int b ) const
{
return this->cost(a) < this->cost(b);
}
};
struct CompEps : public Compare
{
const int eps;
CompEps(const int e) : Compare(), eps(e) {}
virtual bool operator()( const int a, const int b ) const
{
return this->cost(a)-eps < this->cost(b)+eps;
}
};
template<typename C>
struct Algorithm
{
C & comp;
Algorithm(C& comp_) : comp(comp_) {}
virtual void operator()() const = 0;
};
template<typename C>
struct Algo : public Algorithm<C>
{
Algo(C & comp_) : Algorithm<C>(comp_) {}
virtual void operator()() const
{
std::vector<int> costs;
this->comp.attach(costs);
std::priority_queue<int, std::vector<int>, C > queue(this->comp);
}
};
template<typename C>
Algo<C> make_algo(C& comp)
{
return Algo<C>(comp);
}
int main()
{
CompCosts compc;
Algo<CompCosts> algo0(compc);
auto algo1 = make_algo(compc);
CompEps compe(1);
Algo<CompEps> algo2(compe);
auto algo3 = make_algo(compe);
}
EDIT2: as the solution proposed by Barry may not be obvious to everybody, here is the corresponding code:
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <cassert>
struct Compare
{
virtual bool operator()( const int a, const int b, const std::vector<int>& costs ) const =0;
};
struct CompCosts : public Compare
{
virtual bool operator()( const int a, const int b, const std::vector<int>& costs ) const
{
return costs[a] < costs[b];
}
};
struct CompEps : public Compare
{
const int eps;
CompEps(const int e) : Compare(), eps(e) {}
virtual bool operator()( const int a, const int b, const std::vector<int>& costs ) const
{
return costs[a]-eps < costs[b]+eps;
}
};
struct Algorithm
{
std::function<bool(const int, const int, const std::vector<int>& costs )> comp;
Algorithm(
std::function<
bool(const int, const int, const std::vector<int>& costs )
> comp_
) : comp(comp_) {}
virtual void operator()() const = 0;
};
struct Algo : public Algorithm
{
Algo(std::function<bool(const int, const int, const std::vector<int>& costs )> comp_) : Algorithm(comp_) {}
virtual void operator()() const
{
std::vector<int> costs{3,2,1};
using namespace std::placeholders;
std::function<bool(const int, const int)> f = std::bind(comp, _1, _2, std::cref(costs));
std::priority_queue<int, std::vector<int>, std::function<bool(const int, const int )> > queue(f);
}
};
int main()
{
CompCosts compc;
Algo algo0(compc);
algo0();
CompEps compe(0);
Algo algo2(compe);
algo2();
}
Since priority_queue holds onto an object of type Compare, any attempt at polymorphism there would lead to slicing and fail. But polymorphism is just really overthinking the problem anyway (like I did in the previous revision).
Just use type erasure. All your comparators will have a bool operator()(int, int), like:
struct CompCosts
{
std::vector<int> const& costs;
bool compare(int lhs, int rhs) const
{
return costs[lhs] < costs[rhs];
}
};
So they can all be handled by std::function<bool(int, int)>:
using Q = std::priority_queue<int, std::vector<int>, std::function<bool(int, int)>>;
And then just create your Q with whichever comparator you want to use:
Q queue_by_cost(CompCosts{costs});
Q queue_by_eps(CompEps{costs});
I'll paste the relevant code only
Template class:
template<class TMsgType, class TKeyType>
struct mapped_subscription_handler
{
protected:
typedef std::function<void(TKeyType const &, TMsgType*)> handler_t;
typedef std::unordered_multimap<TKeyType, subscr_obj<handler_t>> map_t;
public:
void call(TKeyType const & key, TMsgType* msg)
{
//blah
}
public:
handler_id_t register_handler(TKeyType const & key, handler_t handler)
{
//blah
}
void unregister_handler(TKeyType key, handler_id_t id)
{
//blah
}
private:
map_t _map;
};
Implementation class:
typedef clients::mapped_subscription_handler<NS_Snap::NS_MD::DepSnapshot, clients::header_info<NS_Snap::NS_DEF::Header>::mdid_t> depth_handler_t;
typedef clients::mapped_subscription_handler<NS_Snap::NS_MD::TrdSnapshot, clients::header_info<NS_Snap::NS_DEF::Header>::mdid_t> trd_handler_t;
class data_client
:public depth_handler_t,
public trd_handler_t
{
public:
data_client(const std::string & host, int port);
virtual ~data_client();
clients::handler_id_t register_on_connect(std::function<void()> connect_handler);
using depth_handler_t::register_handler;
using trd_handler_t::register_handler;
using depth_handler_t::unregister_handler;
using trd_handler_t::unregister_handler;
};
Usage:
class time_comparer
{
internal_clients::data_client *_int_client;
void whenever()
{
//Compiler complains about ambiguous call here.
_int_client->register_handler(rep->GetId(), boost::bind(&time_comparer::on_internal_depth, this, _1, _2));
}
void on_internal_depth(uint64_t const & key, NS_Snap::NS_MD::DepSnapshot* depth)
{
//blah
}
};
The compiler complains of ambiguous reference when I call register_handler. Shouldn't it be able to identify which register_handler I am calling (based on boost::bind type)? Otherwise I have to qualify the call with the class name which is ugly.
EDIT:
Based on input from Sebastian Redl
This simpler example encounters the same problem
#include <iostream>
#include <functional>
template<class T>
struct test_template
{
template<class TArg>
void do_(T t, TArg arg)
{
t(arg);
}
};
class test_class :
public test_template<std::function<void(char*)>>,
public test_template<std::function<void(int)>>
{
public:
using test_template<std::function<void(char*)>>::do_;
using test_template<std::function<void(int)>>::do_;
};
int main()
{
test_class tc;
tc.do_([](int x){std::cout << x << std::endl; }, 10);
tc.do_([](char* x) {std::cout << x << std::endl; }, "what");
return 0;
}
Is there any way around this without explicitly specifying the overload when calling? i.e.
tc.test_template<std::function<void(int)>>::do_([](int x){std::cout << x << std::endl; }, 10);
In the simplified example, you may use SFINAE to remove template based mostly on the non function argument.
template<class T>
struct test_template
{
template<class TArg>
auto do_(T t, TArg arg)
-> decltype(t(arg), void())
{
t(arg);
}
};
Live demo
std::function is very liberal in conversions to it, and in particular the standard doesn't require the conversion to be SFINAEd out if the passed function object isn't compatible. So both function types appear to be constructable from the binds, which is why you get an ambiguity.
I'm trying to hold a polymorphic type as a key in a map.
I came up with the following two structures:
Note that Game is an abstract class and the data structure I use is :
std::unordered_map<gamePtr,int> _allGames;
while gamePtr is a typedef for:
unique_ptr<Game>
template<>
struct std::hash<std::unique_ptr<Game>> {
size_t operator()(std::unique_ptr<Game> game) const {
return (std::hash<string>()(std::to_string(game->firstTeamFinalScore()) + game->firstTeam() + game->secondTeam()));
}
};
struct cmp_games {
bool operator() (std::unique_ptr<Game> game1, std::unique_ptr<Game> game2) const {
return *game1 == *game2;
}
};
The cmp_games comparator seems to work fine but the std::hash does not because it tries to copy a unique_ptr (Which is ofc impossible) and I've no idea how to get over it.
Would love to hear some suggestions (If that is even possible).
EDIT: The comparator also doesn't seem to work properly. how do I make this map work correctly with unique_ptr as a key?
EDIT2:
Came up with:
template<>
struct std::hash<std::unique_ptr<Game>> {
size_t operator()(const std::unique_ptr<Game>& game) const {
return (std::hash<string>()(std::to_string(game->firstTeamFinalScore()) + game->firstTeam() + game->secondTeam()));
}
};
template<>
struct std::equal_to<std::unique_ptr<Game>> {
bool operator() (const std::unique_ptr<Game>& game1,const std::unique_ptr<Game>& game2) const {
return *game1 == *game2;
}
};
Should they be enough?
The standard provides a specilization so that std::hash<unique_ptr<T>> is the same as std::hash<T*>. So provide a specialization for std::hash<Game *>. For example:
#include <iostream>
#include <memory>
#include <unordered_map>
#include <cstdlib>
struct foo
{
foo(unsigned i) : i(i) {}
unsigned i;
};
namespace std {
template<>
struct hash<foo *>
{
size_t operator()(foo const *f) const
{
std::cout << "Hashing foo: " << f->i << '\n';
return f->i;;
}
};
}
int main()
{
std::unordered_map<std::unique_ptr<foo>, int> m;
m.insert(std::make_pair(std::unique_ptr<foo>(new foo(10)), 100));
m.insert(std::make_pair(std::unique_ptr<foo>(new foo(20)), 200));
}
Live demo
Another option is to change your existing std::hash specialization so that it takes the unique_ptr by reference.
size_t operator()(std::unique_ptr<Game> const& game) const
// ^^^^^^ no more copying
EDIT: std::unique_ptr provides comparison operators that compare the managed pointers. If you want the unordered_map to test the Game objects themselves for equality, provide an operator== overload instead of specializing std::equal_to
inline bool operator==(const std::unique_ptr<Game>& game1,
const std::unique_ptr<Game>& game2)
{
return *game1 == *game2;
}
This, in turn, requires that you've provided an equality operator for Game (or you could just add the logic to the function above).
inline bool operator==(Game const& game1, Game const& game2)
{
return // however you want to compare these
}
Pass the game by const reference into std::hash::operator():
template<>
struct std::hash<std::unique_ptr<Game>> {
size_t operator()(const std::unique_ptr<Game>& game) const;
}
The same applies to cmp_games::operator().
Basic structure of my code is
class Foo{
vector<string> _lines;
vector<int> _n;
public:
...
bool Comp(int i, int j){
return something that depends on _lines;
}
...
void doSomething(){
std::sort(_n.begin(), _n.end(), Comp);
}
...
};
But I get
error: no matching function for call to
‘sort(std::vector<unsigned int>::iterator,
std::vector<unsigned int>::iterator, <unresolved overloaded function type>)
How can I resolve this problem WITHOUT COPYING THE VECTORS? (because these vectors are very very big 17179508 strings to be precise).
std::sort expects a binary predicate taking two ints in this case. A member function takes an implicit first parameter, so in all Foo::Comp takes three parameters. You could pass a non-member function, or a static member function, but neither of these would have access to Foo's data members. The simples way is to use std::bind to bind this to the first parameter of the member function:
#include <functional> // for std::bind
#include <vector>
#include <algorithm>
class Foo{
vector<string> _lines;
vector<int> _n;
public:
...
bool Comp(int i, int j){
return something that depends on _lines;
}
...
void sort(){
using namespace std::placeholders;
std::sort(_n.begin(), _n.end(), std::bind(Comp, this, _1, _2));
}
...
};
The most obvious initial suggestion is to aggregate your int and string into a struct or std::pair, have a single vector with the aggregate in it, and then sort that vector of aggregates.
But if the two vectors are in fact independent, I would suggest using an external predicate, instead of your Comp method:
struct Comp
{
explicit Comp(vector<string>& lines) : lines_(lines) { }
bool operator()(int i, int j) const
{
return something that depends on lines_;
}
vector<string>& lines_;
};
Then call it:
void doSomething()
{
std::sort(_n.begin(), _n.end(), Comp(_lines));
}
What about using your object as the comparator itself. This compiles on gcc 4.6:
class Foo{
std::vector<std::string> _lines;
std::vector<int> _n;
public:
bool operator()(int i, int j){
return false;
}
void doSomething(){
std::sort(_n.begin(), _n.end(), *this);
}
};
Edit:
Turns out that was not such a good idea, copying an object with 17M strings would incur a huge penalty. A nested class, taking a pointer, could be used instead. That would also allow us to have different comparators:
class Foo
{
std::vector<std::string> _lines;
std::vector<int> _n;
class Bar
{
public:
Bar( const Foo * foo ) : _foo( foo ) {}
bool operator()( int i, int j )
{
act on _foo->_lines
}
private:
const Foo * _foo;
};
public:
void doSomething(){
std::sort(_n.begin(), _n.end(), Bar(this));
}
};
I'm trying to store a set of std::function in a map (under GCC 4.5)
I'd like to get 2 kind of things :
storing functions with arguments already passed; then you just have
to call f()
storing functions without arguments; then you have to call
f(...)
I think I achieved the first one with a class Command and a Manager :
class Command
{
std::function<void()> f_;
public:
Command() {}
Command(std::function<void()> f) : f_(f) {}
void execute() { if(f_) f_(); }
};
class CommandManager
{
typedef map<string, Command*> FMap;
public :
void add(string name, Command* cmd)
{
fmap1.insert(pair<string, Command*>(name, cmd));
}
void execute(string name)
{
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
Command* c = it->second;
c->execute();
}
}
private :
FMap fmap1;
};
can be used like this :
class Print{
public:
void print1(string s, string s1){ cout<<"print1 : "<<"s : "<<s<<" s1 : "<<s1<<endl; }
int print2(){ cout<<"print2"<<endl; return 2;}
};
#include <string>
#include <functional>
int main()
{
Print p = Print();
function<void()> f1(bind(&Print::print1, &p, string("test1"), string("test2")));
function<int()> f2(bind(&Print::print2, &p));
CommandManager cmdMgr = CommandManager();
cmdMgr.add("print1", new Command(f1));
cmdMgr.execute("print1");
cmdMgr.add("print2", new Command(f2));
cmdMgr.execute("print2");
return 0;
}
Now I'd like to be able to do this :
int main()
{
Print p = Print();
function<void(string, string)> f1(bind(&Print::print1, &p, placeholders::_1, placeholders::_2));
CommandManager cmdMgr = CommandManager();
cmdMgr.add("print1", new Command(f1));
cmdMgr.execute("print1", string("test1"), string("test2"));
return 0;
}
Is there a way, using type-erasure for example ?
You could use dynamic cast to determine the type of the function in the list at runtime.
Please note that I added shared_ptr to remove the memory leak in the original sample. Perhaps you want to throw a exception if the execute method is called with the wrong arguments (if the dynamic_cast yields 0).
Usage:
void x() {}
void y(int ) {}
void main() {
CommandManager m;
m.add("print", Command<>(x));
m.add("print1", Command<int>(y));
m.execute("print");
m.execute("print1", 1);
}
Code (with variadic template support for example gcc-4.5):
#include <functional>
#include <map>
#include <string>
#include <memory>
using namespace std;
class BaseCommand
{
public:
virtual ~BaseCommand() {}
};
template <class... ArgTypes>
class Command : public BaseCommand
{
typedef std::function<void(ArgTypes...)> FuncType;
FuncType f_;
public:
Command() {}
Command(FuncType f) : f_(f) {}
void operator()(ArgTypes... args) { if(f_) f_(args...); }
};
class CommandManager
{
typedef shared_ptr<BaseCommand> BaseCommandPtr;
typedef map<string, BaseCommandPtr> FMap;
public :
template <class T>
void add(string name, const T& cmd)
{
fmap1.insert(pair<string, BaseCommandPtr>(name, BaseCommandPtr(new T(cmd))));
}
template <class... ArgTypes>
void execute(string name, ArgTypes... args)
{
typedef Command<ArgTypes...> CommandType;
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
CommandType* c = dynamic_cast<CommandType*>(it->second.get());
if(c)
{
(*c)(args...);
}
}
}
private :
FMap fmap1;
};
without variadic template support (example VS2010):
#include <functional>
#include <map>
#include <string>
#include <memory>
using namespace std;
class Ignored;
class BaseCommand
{
public:
virtual ~BaseCommand() = 0 {};
};
template <class A1 = Ignored>
class Command : public BaseCommand
{
typedef std::function<void(A1)> FuncType;
FuncType f_;
public:
Command() {}
Command(FuncType f) : f_(f) {}
void operator()(const A1& a1) { if(f_) f_(a1); }
};
template <>
class Command<Ignored> : public BaseCommand
{
typedef std::function<void()> FuncType;
FuncType f_;
public:
Command() {}
Command(FuncType f) : f_(f) {}
void operator()() { if(f_) f_(); }
};
class CommandManager
{
typedef shared_ptr<BaseCommand> BaseCommandPtr;
typedef map<string, BaseCommandPtr> FMap;
public :
template <class T>
void add(string name, const T& cmd)
{
fmap1.insert(pair<string, BaseCommandPtr>(name, BaseCommandPtr(new T(cmd))));
}
template <class A1>
void execute(string name, const A1& a1)
{
typedef Command<A1> CommandType;
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
CommandType* c = dynamic_cast<CommandType*>(it->second.get());
if(c)
{
(*c)(a1);
}
}
}
void execute(string name)
{
typedef Command<> CommandType;
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
CommandType* c = dynamic_cast<CommandType*>(it->second.get());
if(c)
{
(*c)();
}
}
}
private :
FMap fmap1;
};
What you are trying to do is not possible without some serious runtime work and the associated cost. The simplest solution would of course to just store a boost::any (any_function never made it into boost) inside your map and do the necessary casts (or add some runtime data that tells you which cast to make), although you should avoid that at any cost and go with fixed arguments or no arguments.
Your users can then modify their functions using bind to match the signature you require.
Edit: In your current scheme I see no reason for CommandManager to store Command* in the map.
Edit2: Also you drop the return type. This could be OK for your use-case but makes this a lot less generic.
Edit3: I worked out some working example of your code using any. I feel that there is some flaw and I really don't see what this should achieve but here it goes:
#include <iostream>
#include <string>
#include <map>
#include <functional>
#include <boost/any.hpp>
class AnyCaller
{
std::map<std::string, boost::any> calls;
public:
AnyCaller() {}
void add(const std::string& name, const boost::any& fun) {
calls[name] = fun;
}
// we always use the throwing version of any_cast
// icbb by error checking
// no arg version
template<typename Ret>
Ret call(const std::string& s) {
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(void)> >(a)();
}
// this should be a variadic template to be actually usable
template<typename Ret, typename T>
Ret call(const std::string& s, T&& arg) {
// we have to assume that our users know what we are actually returning here
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(T)> >(a)(std::forward<T>(arg));
}
virtual ~AnyCaller() {}
};
int foo() { std::cout << "foo" << std::endl; return 1; }
double foo2(int i) { std::cout << "foo2" << std::endl; return double(i); }
int main()
{
AnyCaller c;
c.add("foo", std::function<int(void)>(foo));
c.add("foo2", std::function<double(int)>(foo2));
c.call<int>("foo");
c.call<double, int>("foo2", 1);
// this should throw
c.call<double, int>("foo", 1);
return 0;
}
As for the example using a fixed signature. Just think of what would be the most natural representation of a function you are going to store (looking at your Command example I'd assume it is std::function<void(void)>. Store functions of this type and whenever one your users tries to use it, he has to bind whatever function he wants to use, so it matches this signature.
Your Command class constructor needs a function<void()>. You are trying to feed it a function<void(string,string)>. This is not going to typecheck.
If you need functions that accept variable arguments (like printf), you will need function<> and execute() that accept variable arguments. You need to know how to work with that (in particular, you need a fixed first argument). You are then responsible for type safety, much like with printf.
If you just need a variable number of string arguments, use functions that accept e.g. vectors of strings.
All this has nothing to do whatsoever with std::map. Whatever you can store in a plain old variable, you can store in std::map too.