How to store functional objects with different signatures in modern C++ - c++11

I would like to know if there is a way to store functional objects (functions, callbacks, ...) with different signatures in a standard container (std::map) with modern C++ only. The library that manages the container does not know which signatures will be used by its "clients".
My need is the same as exposed here : How to store functional objects with different signatures in a container?, and this solution https://stackoverflow.com/a/8304873/4042960 is about perfect for me: I would just like to do the same thing without boost. As far as I know, there is no std::any. The best solution for me would be to store std::function without specialized them, but I do not know how to do it, if it is possible.
Edit:
With the answers you give to me I wrote this example :
#include <map>
#include <memory>
#include <functional>
#include <string>
#include <iostream>
#include <stdexcept>
class FunctionMap
{
struct Base {
virtual ~Base() {}
};
template<class R, class... Args>
struct Func : Base
{
std::function<R(Args...)> f;
};
std::map<std::string, std::shared_ptr<Base> > _map;
public:
template<class R, class... Args>
void store(const std::string &key, const std::function<R(Args...)> &f) {
auto pfunc = std::make_shared<Func<R, Args...> >();
pfunc->f = f;
_map.insert(std::make_pair(key, pfunc));
}
template<class R, class... Args>
std::function<R(Args...)> get(const std::string &key) {
auto pfunc = std::dynamic_pointer_cast<Func<R, Args...> >(_map[key]);
if (pfunc)
return pfunc->f;
else
throw std::runtime_error("Bad type for function's parameters");
}
};
// test
int plus(int a, int b) { return a+b; }
double multiplies(double x, double y) { return x*y; }
int main()
{
FunctionMap fm;
fm.store("plus", std::function<int(int, int)>(&plus));
fm.store("multiplies", std::function<double(double, double)>(&multiplies));
// fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1));
std::cout << "5 + 3 = " << fm.get<int, int, int>("plus")(5, 3) << std::endl;
std::cout << "5 * 3 = " << fm.get<double, double, double>("multiplies")(5.0, 3.0) << std::endl;
return 0;
}
This works well, but I would like to improve it a bit:
1) I would like to be able to use std::bind : fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1)); but currently that does not compile ;
2) I would like to use fm.get<int (int, int)>("plus") instead of fm.get<int, int, int>("plus") but I do not know how to do it.
Many thanks for your help !

You can write your own any. Without all the compiler workarounds and stuff, boost::any can be written in about 30 lines of code.

Function objects are in no way different from any other kind of objects, so anything applicable to objects in general is applicable to function objects.
So you want to store different kinds of (function) objects in a map. This is normally done by storing (smart) pointers to a base class, where each derived class holds its own kind of objects you want to store.
struct Base {
virtual ~Base(){}
};
template <typename A>
struct Object : Base {
A value;
};
That's your basic caveman's boost::any. Your clients do something like this:
Base* b = mymap["foo"];
dynamic_cast<Object<void(*)(int)>*>(b)->val(123);
But with appropriate checks of course.

Related

C++ std::unordered_map key custom hashing

I've got the following test.cpp file
#include <string>
#include <functional>
#include <unordered_map>
#include <iostream>
class Mystuff {
public:
std::string key1;
int key2;
public:
Mystuff(std::string _key1, int _key2)
: key1(_key1)
, key2(_key2)
{}
};
namespace std {
template<>
struct hash<Mystuff *> {
size_t operator()(Mystuff * const& any) const {
size_t hashres = std::hash<std::string>()(any->key1);
hashres ^= std::hash<int>()(any->key2);
std::cout << "Hash for find/insert is [" << hashres << "]" << std::endl;
return (hashres);
}
};
}; /* eof namespace std */
typedef std::unordered_map<Mystuff *, Mystuff *>mystuff_map_t;
mystuff_map_t map;
int insert_if_not_there(Mystuff * stuff) {
std::cout << "Trying insert for " << stuff->key1 << std::endl;
if (map.find(stuff) != map.end()) {
std::cout << "It's there already..." << std::endl;
return (-1);
} else {
map[stuff] = stuff;
std::cout << "Worked..." << std::endl;
}
return (0);
}
int main(){
Mystuff first("first", 1);
Mystuff second("second", 2);
Mystuff third("third", 3);
Mystuff third_duplicate("third", 3);
insert_if_not_there(&first);
insert_if_not_there(&second);
insert_if_not_there(&third);
insert_if_not_there(&third_duplicate);
}
You can compile with g++ -o test test.cpp -std=gnu++11.
I don't get what I'm doing wrong with it: the hash keying algorithm is definitely working, but for some reason (which is obviously in the - bad - way I'm doing something), third_duplicate is inserted as well in the map, while I'd wish it wasn't.
What am I doing wrong?
IIRC unordered containers need operator== as well as std::hash. Without it, I'd expect a compilation error. Except that your key is actually MyStuff* - the pointer, not the value.
That means you get the duplicate key stored as a separate item because it's actually not, to unordered_map, a real duplicate - it has a different address, and address equality is how unordered_map is judging equality.
Simple solution - use std::unordered_map<Mystuff,Mystuff> instead. You will need to overload operator== (or there's IIRC some alternative template, similar to std::hash, that you can specialize). You'll also need to change your std::hash to also accept the value rather than the pointer.
Don't over-use pointers in C++, especially not raw pointers. For pass-by-reference, prefer references to pointers (that's a C++-specific meaning of "reference" vs. "pointer"). For containers, the normal default is to use the type directly for content, though there are cases where you might want a pointer (or a smart pointer) instead.
I haven't thoroughly checked your code - there may be more issues than I caught.

Runtime iteration over tuple types without construction

I have a std::tuple (or a boost fusion tuple) whose elements cannot be trivially constructed (for example references) and I want to iterate over the types but not the values of the elements.
In this example I have a (general) tuple type and I want to generate a vector with (runtime) type information. The example below works if all the types in the sequence are trivially default constructed but not in general.
In summary, I want a function that transform: std::tuple<...> -> std::vector<std::type_index>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <typeindex>
#include<vector>
using tuple_type = std::tuple<std::string&, int>;
int main(){
std::vector<std::type_index> types;
boost::fusion::for_each(
tuple_type{}, // fails because of std::string&
[&types](auto& e){types.push_back(typeid(e));}
);
}
The problem is that I have to generate runtime information from non runtime information and I can't figure out how to mix the fusion functions (http://www.boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/algorithm/iteration/functions.html) and the metafunctions (http://www.boost.org/doc/libs/1_41_0/libs/fusion/doc/html/fusion/algorithm/iteration/metafunctions.html).
I tried with boost::fusion::accumulate and boost::fold but the situation is always the same, at some point I have to generate a runtime element in order to apply the algorithm.
EDIT: I solved the original problem (std::tuple<...> -> std::vector<std::type_index>). I can't imagine another context at the moment but maybe the fundamental question still stands.
I did it by using a trick involving expanding a parameter pack over the typeid function in the constructor of std::vector (or std::array).
template<class... Args>
std::array<std::type_index, sizeof...(Args)> const& types_info<std::tuple<Args...>>::value{typeid(Args)...};
The complete code is this (note that I also decided to use std::array).
#include <typeindex>
#include<array>
#include<iostream>
template<class T>
struct types_info;
template<class... Args>
struct types_info<std::tuple<Args...>>{
static std::array<std::type_index, sizeof...(Args)> const& value;//{typeid(Args)...};
};
template<class... Args>
std::array<std::type_index, sizeof...(Args)> const& types_info<std::tuple<Args...>>::value{typeid(Args)...};
// vvv works only in C++1z
template<template<typename...> typename T, class... Args> // non tuples types as well
struct types_info<T<Args...>> : types_info<std::tuple<Args...>>{};
using tuple_type = std::tuple<std::string&, int>;
int main(){
std::vector<std::type_index> types;
std::cout << types_info<tuple_type>::value.size() << std::endl;
std::cout << types_info<std::map<int, std::string>>::value.size() << std::endl;
}

std::initializer_list with Multiple Types

I'm having trouble with std::initializer_list. I reduced it down to a simple example:
#include <initializer_list>
#include <cstdio>
class Test {
public:
template <typename type> Test(const std::initializer_list<type>& args) {}
};
int main(int argc, char* argv[]) {
Test({1,2});
getchar();
return 0;
}
When compiled using g++ test_initializer.cpp -std=c++0x, it compiles and runs well. However, if line 11 is changed to Test({1,2.0});, one gets:
ian#<host>:~/Desktop$ g++ test_initializer.cpp -std=c++0x
test_initializer.cpp: In function ‘int main(int, char**)’:
test_initializer.cpp:11:14: error: no matching function for call to ‘Test::Test(<brace-enclosed initializer list>)’
test_initializer.cpp:11:14: note: candidates are:
test_initializer.cpp:7:28: note: template<class type> Test::Test(const std::initializer_list<_Tp>&)
test_initializer.cpp:5:7: note: constexpr Test::Test(const Test&)
test_initializer.cpp:5:7: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const Test&’
test_initializer.cpp:5:7: note: constexpr Test::Test(Test&&)
test_initializer.cpp:5:7: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘Test&&’
I suspect this happens because the compiler can't figure out what type to make the initializer list. Is there a way to fix the example so that it works with different types (and still uses initializer lists)?
An std::initializer_list takes only one type. If you need different types, you can use variadic templates:
template<typename... Args>
Test(Args&&... args);
/* ... */
int main()
{
Test(1, 2.0);
}
Would a std::tuple<int.double> work for the OP? If the code will always have a int followed by a double, then the OP could get strict type-checking for all arguments, which the variable arguments solution does not allow. The std::tuple<>, however, would not work for any number or order of values, so may not be appropriate for all use cases.
Let the initializer_list hold the most arbitrary pointers, void*, and do your own casting from there. Here is an example.
#include <initializer_list>
#include <iostream>
using std::initializer_list;
using std::cout;
using std::endl;
class Person {
private:
string _name;
int _age;
public:
Person(initializer_list<void*> init_list) {
auto it = init_list.begin();
_name = *((string*)(*it));
it++;
_age = *((int*)(*it));
}
void print() {
cout << "name: " << _name << ". age: " << _age << endl;
}
};
int main(void) {
string name{"Vanderbutenburg};
int age{23};
Person p{&name,&age};
p.print(); // "name: Vanderbutenburg. age: 23"
return 0;
}

Google Test and boost::variant

I wish to iterate over the types in my boost::variant within my unit test. This can be done as follows:
TEST_F (MyTest, testExucutedForIntsOnly)
{
typedef boost::variant<int, char, bool, double> var;
boost::mpl::for_each<SyntaxTree::Command::types>(function());
...
}
Where function is a functor. I simply want to ensure that a particular operation occurs differently for one type in the variant with respect to all others. However, I don't like that the test is now done in another function -- and what if I wish to access members for MyTest from the functor? It seems really messy.
Any suggestions on a better approach?
So, you want to call a function on a boost::variant that is type-dependent?
Try this:
template<typename T>
struct RunOnlyOnType_Helper
{
std::function<void(T)> func;
template<typename U>
void operator()( U unused ) {}
void operator()( T t ) { func(t); }
RunOnlyOnType_Helper(std::function<void(T)> func_):func(func_){}
};
template<typename T, typename Variant>
void RunOnlyOnType( Variant v, std::function< void(T) > func )
{
boost::apply_visitor( RunOnlyOnType_Helper<T>(func), v );
}
The idea is that RunOnlyOnType is a function that takes a variant and a functor on a particular type from the variant, and executes the functor if and only if the type of the variant matches the functor.
Then you can do this:
typedef boost::variant<int, char, bool, double> var;
var v(int(7)); // create a variant which is an int that has value 7
std::string bob = "you fool!\n";
RunOnlyOnType<int>( v, [&](int value)->void
{
// code goes here, and it can see variables from enclosing scope
// the value of v as an int is passed in as the argument value
std::cout << "V is an int with value " << value << " and bob says " << bob;
});
Is that what you want?
Disclaimer: I have never touched boost::variant before, the above has not been compiled, and this is based off of quickly reading the boost docs. In addition, the use of std::function above is sub-optimal (you should be able to use templated functors all the way down -- heck, you can probably extract the type T from the type signature of the functor).

Priority of a priority queue always needs to be integral?

I'm just curious if I can have any other data type to give the priority? Like strings, floats, etc?
In the abstract, any type with a reasonable Strict Weak Ordering can be used as the priority in a priority queue. The language you are using will determine how to define this ordering: in C++, operator< is used in standard containers, in Java, the interface Comparable and function compareTo are typically used. Custom comparison functions are also often supported, which can compare elements in a manner different than the default.
No.
The ordering element of a priority queue does not have to be integral.
Yes.
You can use whatever type you want, as long as two values of that type can be compared to determine their inherent ordering.
Basically, you can build a priority queue that uses whatever type you want, even a complex number if you can determine an ordering that makes sense for those.
There is, however, another, unasked, question here, for which the answer is:
Yes, most existing implementations of a priority queue will use an integer as the ordering element as that is the easiest, and most common, value used for this purpose.
Here is a fullblown C++ demo of how to queue SillyJobs, defined as
struct SillyJob
{
std::string description;
std::string priority;
// ...
};
It does so in two ways: using the member operator< (default) and by passing an explicit comparison predicate to priority_queue constructor.
Let's see the output up-front:
Silly: (by description length)
LOW: very very long description
HIGH: short
------------------------------------------------------------
Not so silly: (by priority value)
HIGH: short
LOW: very very long description
See it live on http://ideone.com/VEEQa
#include <queue>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
#include <map>
struct SillyJob
{
std::string description;
std::string priority;
SillyJob(const std::string& d, const std::string& p)
: description(d), priority(p) { }
bool operator<(const SillyJob& sj) const { return description.size() < sj.description.size(); }
friend std::ostream& operator<<(std::ostream& os, const SillyJob& sj)
{ return os << sj.priority << ": " << sj.description; }
};
static bool by_priority(const SillyJob& a, const SillyJob& b)
{
static std::map<std::string, int> prio_map;
if (prio_map.empty())
{
prio_map["HIGH"] = 3;
prio_map["MEDIUM"] = 2;
prio_map["LOW"] = 1;
}
return prio_map[a.priority] < prio_map[b.priority];
}
int main()
{
std::cout << "Silly: (by description length)" << std::endl;
{
// by description length (member operator<)
std::priority_queue<SillyJob> silly_queue;
silly_queue.push(SillyJob("short", "HIGH"));
silly_queue.push(SillyJob("very very long description", "LOW"));
while (!silly_queue.empty())
{
std::cout << silly_queue.top() << std::endl;
silly_queue.pop();
}
}
std::cout << std::string(60, '-') << "\nNot so silly: (by priority value)" << std::endl;
{
// by description length (member operator<)
typedef bool (*cmpf)(const SillyJob&, const SillyJob&);
typedef std::priority_queue<SillyJob, std::vector<SillyJob>, cmpf> not_so_silly_queue;
not_so_silly_queue queue(by_priority);
queue.push(SillyJob("short", "HIGH"));
queue.push(SillyJob("very very long description", "LOW"));
while (!queue.empty())
{
std::cout << queue.top() << std::endl;
queue.pop();
}
}
}
PS. The by_priority comparison function is quite a good example of bad design, but bear in mind it was for demonstrational purposes only :)
You can use any type for priority if the values of the type can be compared with each other.

Resources