How to reimplement this with std algorithms? - c++

I have a container of pointers to objects. The pointers are a base class, and the hierarchy implements a virtual function count(). I want to calculate a sum of count() in the container.
I currently do this with for_each and a lambda function:
size_t sum = 0;
std::for_each(ptrs_.begin(), ptrs_.end(), [&sum](ptr const *p) {
expr += p->count();
});
return sum;
Can anyone help me reimplement this with boost::bind and std::accumulate or other std algorithms?

auto getcount = std::mem_fun(&Base::count); // nothing to bind, we just need a functor
size_t sum = std::accumulate(
boost::make_transform_iterator(ptrs_.begin(), getcount),
boost::make_transform_iterator(ptrs_.end(), getcount),
(size_t)0
);
If you don't like auto, or more likely if your compiler doesn't, then of course you can paste the thing twice, or go looking for the return type of mem_fun, or capture it using a function template:
template <typename IT, typename FUNC, typename T>
T transform_accumulate(IT first, IT last, T init, FUNC func) {
return std::accumulate(
boost::make_transform_iterator(first, func),
boost::make_transform_iterator(last, func),
init
);
}
Then call it as:
transform_accumulate(ptrs_.begin(), ptrs_.end(), size_t(), std::mem_fun(&Base::count));
Alternately, use the form of std::accumulate that takes a binary functor:
struct AddCount {
size_t operator()(size_t result, Base *p) const {
return result + p->count();
}
};
size_t sum = std::accumulate(ptrs_.begin(), ptrs_.end(), size_t(), AddCount());
Instead of writing AddCount, you could of course use a lambda expression. I expect you can construct it using the stuff in <functional> too, but I'm not going to.
I haven't tested any of this code, so let the error-spotting begin!

Related

Function-typed member variable selecting from iterators

Goals
A class with a function-typed member variable that can be used to choose a value from a range of values denoted by two iterators
Should work in C++14, but if a (much) better solution is only possible in 17 or 20, I'd be interested nonetheless
Problem and Solution Sketch
Below is a sketch of the envisioned solution, with ??? denoting the choose-function's type, which I can't work out.
template<typename E>
class Producer {
??? choose_from; // A function It × It → E
...
public:
Producer(??? cf): choose_from{cf} {}
E next() {
// Get a bunch of values from internal state (omitted for brevity).
// Could also be another container, e.g. std::set.
std::vector<E> values = ...;
return choose_from(values.begin(), values.end());
}
}
Next up, a few example usage sketches of such a Producer. A solution that only supports a subset of those would still be fine.
In combination with an existing function:
auto p = Producer<int>(std::max_element)`;
In combination with a lambda function:
auto p = Producer<int>([](auto begin, auto end)) { ... });
In combination with a custom free function:
template<typename E, typename It>
E my_selector(It begin, It end) { ... }
auto p = Producer<int>(my_selector);
Question
How do I get the code to work, i.e. what's the/a right type for member variable choose_from?
Attempt & Thoughts
I've tried to use std::function to type choose_from, but since there is no abstract iterator type (AFAIK), I'm basically stuck at std::function<E(IT?, IT?)>.
If the use of std::vector in Producer::next() were leaked, I could fix choose_from's type to handle std::vector<E>::iterators, but I'd much rather keep that internal detail hidden.
std::min_element is a function template, there isn't much you can do with it by itself. Function templates are problematic - they can't be passed as a template argument, nor as function argument.
If you're OK with wrapping it in a generic lambda, then there's a generic solution possible:
template<class E, class F>
class Producer {
F choose_from; // A function It - It → It
public:
Producer(F const& cf) : choose_from{ cf } {}
E next() {
std::vector<E> values{ 5, 2, 3 };
return *choose_from(values.begin(), values.end());
}
};
template<typename E, typename F>
auto make_producer(F const& cf) {
return Producer<E, F>(cf);
}
template<typename It>
It my_selector(It begin, It end) { return begin; }
int main() {
auto p1 = make_producer<int>([](auto from, auto to) { return from; });
cout << p1.next() << endl;
auto p2 = make_producer<int>([](auto from, auto to) { return std::min_element(from, to); });
cout << p2.next() << endl;
auto p3 = make_producer<int>([](auto from, auto to) { return my_selector(from, to); });
cout << p3.next() << endl;
}
Notes:
There's also no partial CTAD, so even in C++17 you'd need a helper function (make_producer() above).
std::function comes with run-time overhead (1..2 extra indirections). It should be used only when run-time polymorphism is unavoidable (e.g. dynamic callbacks) -- not the case here. Do not use.

Set a C-style array with template function accepting callback

So, let's say I'm writing a function to set an array using a user-supplied callback per item. (I'm not, but let's suppose I am, for the purposes of a minimal example)
The cleanest way I can find to do this is the following:
#include <functional>
template<typename T, typename Y>
void PopulateArray(std::function<int(Y*)> callback, T &pArray)
{
for (int i = 0; i < sizeof(pArray); ++i)
int x = callback(&pArray[i]);
}
int main()
{
uint64_t myArray[5];
uint64_t myUint = 42;
PopulateArray( (std::function<int(uint64_t*)>) [=](auto x) {*x = myUint; return 0; },
myArray);
}
I have two issues with the code above.
1) For T to be an array type, there seems to be no way to modify the parameter. (I can't say I want an array of type T, meaning I have to declare Y separately, even though they are both related to uint64_t.) I would prefer to declare a single T, with one parameter being a pointer to T and the other being an array of T.
2) The client code (in main), is forced to cast the lambda. Changing auto x to an explicit type doesn't seem to help matters.
Is there a resolution to #1 or #2 that might make the code more succinct or readable?
Code will need to compile with gcc, clang, and VS. I think C++11 is the newest standard I can use, although I'd be interested in C++14 solutions, as that would be a matter of upgrading our clang build process. I'm not interested in solutions that involve switching myArray to std::array std::vector, etc..
Drop the requirement for std::function:
// You could consider using an array type for the parameter:
// template <typename Callback, typename T, std::size_t N>
// void PopulateArray(Callback callback, T (&pArray)[N])
template<typename Callback, typename T>
void PopulateArray(Callback callback, T& pArray)
{
// sizeof(pArray) as in the question is almost certainly not what you
// want. It returns the size *in bytes*, not the length of the array.
// Thus, if you specified this to take an array reference,
// `for (std::size_t i = 0; i < N; ++i)` would be correct.
// However, as Barry mentioned in the comments, a range-based for loop
// is the best solution.
for (T& element : pArray)
callback(&element);
}
int main()
{
std::uint64_t myArray[5];
PopulateArray([](auto x) {*x = 42; return 0; },
myArray);
}
std::function is an expensive type. It uses virtual function calls (or techniques that are very similar) and has the potential to allocate memory. If you are not storing the function and especially if the function is already a template, just take an arbitrary callback as your parameter. If you really want to constrain the callback's type, use a function_ref type (not yet standardized), or check that callback(your, args) is valid:
template<typename Callback, typename T>
auto PopulateArray(Callback callback, T& pArray)
-> decltype(callback(*std::begin(pArray)), void())
{
for (T& element : pArray)
callback(&element);
}
Also, in this specific case, you can use an algorithm:
int main()
{
uint64_t myArray[5];
uint64_t myUint = 42;
// If it's all the same value:
std::fill(std::begin(myArray), std::end(myArray), myUint);
// To call a function to populate the array:
std::generate(std::begin(myArray), std::end(myArray), [myUint] {
return myUint;
});
// Or possibly:
std::for_each(std::begin(myArray), std::end(myArray),
[myUint](uint64_t& element) {
element = myUint;
});
}

Need to Total Fields From a Container of structs

This is more of a code clenliness question, cause I already have an example here. I'm doing this a ton in code and the creation of all these lambdas (some of which are the same) has begun to irk me.
So given the struct:
struct foo {
int b() const { return _b; }
int a() const { return _a; }
int r() const { return _r; }
const int _b;
const int _a;
const int _r;
};
I have a container of pointers to them, let's say vector<foo*> foos, now I want to go through the container and get the sum of one of the fields.
As an example if I wanted the field _r, then my current approach is to do this:
accumulate(cbegin(foos), cend(foos), 0, [](const auto init, const auto i) { return init + i->r(); } )
I'm writing this line everywhere. Can any improvement be made upon this? I'd really like to write something like this:
x(cbegin(foos), cend(foos), mem_fn(&foo::r));
I don't think the standard provides anything like that. I could obviously write it, but then it would require the reader to go figure out my suspect code instead of just knowing what accumulate does.
Instead of writing a custom accumulate, I suggest writing a custom functor generator, that returns a functor that can be used as an argument to std::accumulate.
template<class Fun>
auto mem_accumulator(Fun member_function) {
return [=](auto init, auto i) {
return init + (i->*member_function)();
};
}
then
accumulate(cbegin(foos), cend(foos), 0, mem_accumulator(&foo::r));
A few variations:
For containers of objects:
template<class MemFun>
auto mem_accumulator(MemFun member_function) {
return [=](auto init, auto i) {
return init + (i.*member_function)();
};
}
Use data member pointers instead of functions:
template<class T>
auto mem_accumulator(T member_ptr) {
return [=](auto init, auto i) {
return init + i->*member_ptr;
};
}
// ...
accumulator(&foo::_r)
Support functors, rather than member function pointers:
template<class Fun>
auto accumulator(Fun fun) {
return [=](auto init, auto i) {
return init + fun(i);
};
}
// ...
accumulator(std::mem_fun(&foo::r))
Some (all?) of these variations could perhaps be combined to be selected automatically with some SFINAE magic, but that will increase complexity.
There is actually a really elegant way to solve this using Variable Templates which were introduced in c++14. We can templatize a lambda variable using the method pointer as the template argument:
template <int (foo::*T)()>
auto func = [](const auto init, const auto i){ return init + (i->*T)(); };
Passing the func appropriate specialization of func as the last argument to accumulate will have the same effect as writing out the lambda in place:
accumulate(cbegin(foos), cend(foos), 0, func<&foo::r>)
Live Example
Another alternative based off the same templatization premise, which does not require c++14, is the templatized function suggested by StoryTeller:
template <int (foo::*T)()>
int func(const int init, const foo* i) { return init + (i->*T)(); }
Which could also be used by simply passing the method pointer:
accumulate(cbegin(foos), cend(foos), 0, &func<&foo::r>)
Live Example
The specificity required by both these examples has been removed in c++17 where we can use auto for template parameter types: http://en.cppreference.com/w/cpp/language/auto This will allow us to declare func so it can be used by any class, not just foo:
template <auto T>
auto func(const auto init, const auto i) { return init + (i->*T)(); }

Containers for different signature functions

I'm trying to programming in C++ a framework where the user can indicates a set of functions inside its program where he wants to apply a memoization strategy.
So let's suppose that we have 5 functions in our program f1...f5 and we want to avoid the (expensive) re-computation for the functions f1 and f3 if we already called them with the same input. Notice that each function can have different return and argument types.
I found this solution for the problem, but you can use only double and int.
MY SOLUTION
Ok I wrote this solution for my problem, but I don't know if it's efficient, typesafe or can be written in any more elegant way.
template <typename ReturnType, typename... Args>
function<ReturnType(Args...)> memoize(function<ReturnType(Args...)> func)
{
return ([=](Args... args) mutable {
static map<tuple<Args...>, ReturnType> cache;
tuple<Args...> t(args...);
auto result = cache.insert(make_pair(t, ReturnType{}));
if (result.second) {
// insertion succeeded so the value wasn't cached already
result.first->second = func(args...);
}
return result.first->second;
});
}
struct MultiMemoizator
{
map<string, boost::any> multiCache;
template <typename ReturnType, typename... Args>
void addFunction(string name, function < ReturnType(Args...)> func) {
function < ReturnType(Args...)> cachedFunc = memoize(func);
boost::any anyCachedFunc = cachedFunc;
auto result = multiCache.insert(pair<string, boost::any>(name,anyCachedFunc));
if (!result.second)
cout << "ERROR: key " + name + " was already inserted" << endl;
}
template <typename ReturnType, typename... Args>
ReturnType callFunction(string name, Args... args) {
auto it = multiCache.find(name);
if (it == multiCache.end())
throw KeyNotFound(name);
boost::any anyCachedFunc = it->second;
function < ReturnType(Args...)> cachedFunc = boost::any_cast<function<ReturnType(Args...)>> (anyCachedFunc);
return cachedFunc(args...);
}
};
And this is a possible main:
int main()
{
function<int(int)> intFun = [](int i) {return ++i; };
function<string(string)> stringFun = [](string s) {
return "Hello "+s;
};
MultiMemoizator mem;
mem.addFunction("intFun",intFun);
mem.addFunction("stringFun", stringFun);
try
{
cout << mem.callFunction<int, int>("intFun", 1)<<endl;//print 2
cout << mem.callFunction<string, string>("stringFun", " World!") << endl;//print Hello World!
cout << mem.callFunction<string, string>("TrumpIsADickHead", " World!") << endl;//KeyNotFound thrown
}
catch (boost::bad_any_cast e)
{
cout << "Bad function calling: "<<e.what()<<endl;
return 1;
}
catch (KeyNotFound e)
{
cout << e.what()<<endl;
return 1;
}
}
How about something like this:
template <typename result_t, typename... args_t>
class Memoizer
{
public:
typedef result_t (*function_t)(args_t...);
Memoizer(function_t func) : m_func(func) {}
result_t operator() (args_t... args)
{
auto args_tuple = make_tuple(args...);
auto it = m_results.find(args_tuple);
if (it != m_results.end())
return it->second;
result_t result = m_func(args...);
m_results.insert(make_pair(args_tuple, result));
return result;
}
protected:
function_t m_func;
map<tuple<args_t...>, result_t> m_results;
};
Usage is like this:
// could create make_memoizer like make_tuple to eliminate the template arguments
Memoizer<double, double> memo(fabs);
cout << memo(-123.456);
cout << memo(-123.456); // not recomputed
It's pretty hard to guess at how you're planning to use the functions, with or without memoisation, but for the container-of-various-function<>s aspect you just need a common base class:
#include <iostream>
#include <vector>
#include <functional>
struct Any_Function
{
virtual ~Any_Function() {}
};
template <typename Ret, typename... Args>
struct Function : Any_Function, std::function<Ret(Args...)>
{
template <typename T>
Function(T& f)
: std::function<Ret(Args...)>(f)
{ }
};
int main()
{
std::vector<Any_Function*> fun_vect;
auto* p = new Function<int, double, double, int> { [](double i, double j, int z) {
return int(i + j + z);
} };
fun_vect.push_back(p);
}
The problem with this is how to make it type-safe. Look at this code:
MultiMemoizator mm;
std::string name = "identity";
mm.addFunction(name, identity);
auto result = mm.callFunction(name, 1);
Is the last line correct? Does callFunction have the right number of parameters with the right types? And what is the return type?
The compiler has no way to know that: it has no way of understanding that name is "identity" and even if it did, no way to associate that with the type of the function. And this is not specific to C++, any statically-typed language is going to have the same problem.
One solution (which is basically the one given in Tony D's answer) is to tell the compiler the function signature when you call the function. And if you say it wrong, a runtime error occurs. That could look something like this (you only need to explicitly specify the return type, since the number and type of parameters is inferred):
auto result = mm.callFunction<int>(name, 1);
But this is inelegant and error-prone.
Depending on your exact requirements, what might work better is to use "smart" keys, instead of strings: the key has the function signature embedded in its type, so you don't have to worry about specifying it correctly. That could look something like:
Key<int(int)> identityKey;
mm.addFunction(identityKey, identity);
auto result = mm.callFunction(identityKey, 1);
This way, the types are checked at compile time (both for addFunction and callFunction), which should give you exactly what you want.
I haven't actually implemented this in C++, but I don't see any reason why it should be hard or impossible. Especially since doing something very similar in C# is simple.
you can use vector of functions with signature like void someFunction(void *r, ...) where r is a pointer to result and ... is variadic argument list. Warning: unpacking argument list is really inconvenient and looks more like a hack.
At first glance, how about defining a type that has template arguments that differ for each function, i.e.:
template <class RetType, class ArgType>
class AbstractFunction {
//etc.
}
have the AbstractFunction take a function pointer to the functions f1-f5 with template specializations different for each function. You can then have a generic run_memoized() function, either as a member function of AbstractFunction or a templated function that takes an AbstractFunction as an argument and maintains a memo as it runs it.
The hardest part will be if the functions f1-f5 have more than one argument, in which case you'll need to do some funky things with arglists as template parameters but I think C++14 has some features that might make this possible. An alternative is to rewrite f1-f5 so that they all take a single struct as an argument rather than multiple arguments.
EDIT: Having seen your problem 1, the problem you're running into is that you want to have a data structure whose values are memoized functions, each of which could have different arguments.
I, personally, would solve this just by making the data structure use void* to represent the individual memoized functions, and then in the callFunction() method use an unsafe type cast from void* to the templated MemoizedFunction type you need (you may need to allocate MemoizedFunctions with the "new" operator so that you can convert them to and from void*s.)
If the lack of type safety here irks you, good for you, in that case it may be a reasonable option just to make hand-written helper methods for each of f1-f5 and have callFunction() dispatch one of those functions based on the input string. This will let you use compile-time type checking.
EDIT #2: If you are going to use this approach, you need to change the API for callFunction() slightly so that callFunction has template args matching the return and argument types of the function, for example:
int result = callFunction<int, arglist(double, float)>("double_and_float_to_int", 3.5, 4);
and if the user of this API ever types the argument type or return types incorrectly when using callFunction... pray for their soul because things will explode in very ugly ways.
EDIT #3: You can to some extent do the type checking you need at runtime using std::type_info and storing the typeid() of the argument type and return type in your MemoizedFunction so that you can check whether the template arguments in callFunction() are correct before calling - so you can prevent the explosion above. But this will add a bit of overhead every time you call the function (you could wrap this in a IF_DEBUG_MODE macro to only add this overhead during testing and not in production.)

C++ Templated Delegates like Unity

after saw Unity's delegates and events, i'm trying to code my own:
I want to create a class with a variadic template, to specify the return type of the functions, and optionals arguments.
template <typename Ret, typename... Args>
class MyDelegate{
std::vector<Ret(*)(Args...)> vec;
public:
void operator+=( const Ret(*)(Args...)& newElement)
{
vec.push_back(newElement);
}
Ret operator()(const Args&... args)
{
for (auto i = vec.begin(); i != vec.end(); ++i)
(*i)(args...);
}
};
As you can see, i would like this class to be used this way:
MyDelegate<void> voidDelegate;
MyDelegate<void, int> intDelegate;
MyDelegate<int, char, boolt> miscDelegate;
and "adding" functions to each one using += operators, like:
voidDelegate += voidFunc;
//etc...
I'm having problem with the += operator for now, because VS don't accept this:
MyDelegate<void, int> delegate1;
delegate1 += [](const int a)->void{std::cout << a << std::endl; };
The lambda function is correct: it take an int and return void, so i don't understand whats' wrong.
The issue is that your std::vector stores function pointers. It doesn't store std::bind objects, it doesn't store member functions, it doesn't store functors and it doesn't store lambdas. You are trying to add a lambda to it, hence the failure.
If you want to store any kind of object which supports calling with the correct argument and return types, you want std::function:
using FunType = std::function<Ret(Args...)>;
std::vector<FunType> vec;
Demo
Incidentally, you could improve your solution by perfect-forwarding your operator() args and copying your newElement arg in the interface and moving it into the std::vector.
Your delegate accepts only function pointers. A lambda is not a function pointer. However, the lambda that you are trying to doesn't capture anything. Which means that it can be converted to a function pointer thanks to some sorcery:
MyDelegate<void, int> delegate1;
delegate1 += +[](const int a)->void{std::cout << a << std::endl; };
↑↑↑
However, once you want to allow functors that have member variables, the extra + won't work:
delegate1 += +[x](const int a) { ... }; // error: no match for operator+
At which point you'll definitely have to use TartanLlama's suggestions of std::function.
#TartanLlama's right, std::function is what you need.
And the calling loop can be folded to for (auto handler : vec) handler(args...);