Set a C-style array with template function accepting callback - c++

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;
});
}

Related

Forward use of function parameter

I have remembered now that I saw something like this in C:
void foo(int bar; char baz[bar]) { ... }
I don't remember its name or the valid syntax and I wonder if it's available in C++ too?
No, that's not possible according to the standard, since you are dynamically passing the size of the array to the function, unless there is some special compiler extension that I'm missing.
What you can do is to specify it as a template argument and let the deduction do its work, eg:
template<size_t size>
void foo (char (&a)[size])
{
for (size_t i = 0; i < size; ++i)
cout << a[i] << endl;
}
int main()
{
char a[] = {'a','b','c','d','e'};
foo(a);
return 0;
}
Or, since you are working with C++, use an std::array or std::vector and iterators.
For starters, char baz[10] when used as a parameter declares a pointer, not an array, so 10 is completely ignored. This is called array decay to pointer and it's an unfortunate inheritance from C.
Considering you weren't asking strictly about array size, and expanding your question to any use of a previous parameter, the case would be default arguments. E.g.
void foo(int a, int b = a);
And here the answer is again no, it is not valid.
See this answer: https://stackoverflow.com/a/1880877/2805305 for standard justification.
Actually, there is some "Forward use of function parameter" in C++, but not what you are talking about.
Since C++11, you can do stuff like this to deduce type of parameters (or return type) using previous parameter:
template <typename T>
auto get (T const& t, size_t i) -> decltype(t[i]) { }
Or:
template <typename T>
void set (T &t, size_t i, decltype(t[i]) const& v) { }
Maybe I am completely off, but since you did not remember exactly what you saw, I thought this might have been stuff like this.

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.)

keep complete type of a function pointers parameters in template deduction

I'm trying to get a way to keep the complete type of a function pointer's parameters when passed into a template function.
This is an example of what I'd like to do:
#include <stdio.h>
#include <utility>
template<typename _Ret, typename... Args>
static _Ret call(_Ret (*fp)(Args&&...), Args &&... args)
{
return fp(std::forward<Args>(args)...);
}
int foo(int arr[4])
{
printf("arr: %i,%i,%i,%i\n", arr[0], arr[1], arr[2], arr[3]);
return 0;
}
int main(int, char**)
{
int arr[4] = { 1, 2, 3, 4 };
int (*foo_ptr)(int arr[4]) = &foo;
call<int>(foo_ptr, arr);
return 0;
}
Unfortunately the type that call actually sees foo_ptr as int (*)(int*) rather than int (*)(int [4]) or int (*)(int (&)[4]).
The reason for the rvalue references is that is the only way to keep the array's type at all, but it doesn't seem to work for function pointer parameters.
As to why I want to do this, I have a nearly magical lua binding lib that is 100% template based, and requires no code to link to. In order for it to be able to support binding to properties and variables that are arrays themselves the rvalue references are required. int* and int (&)[4] are not compatible types.
The idea is to allow binding existing apis, even C apis as transparently and automagically as possible, while doing as much of the type checking at compile time as is possible.
Is this possible at all?
Edit:
Ok, my example was probably a bit too simplified. I can't actually change the definition of the functions that get passed into "call", as this library is meant to allow binding to any random function a user might want.
here for example is my static function (non method) binding method:
template<typename _Ret, typename... _Args>
LuaGlue &func(const std::string &name, _Ret (*fn)(_Args...))
{
auto new_func = new LuaGlueFunction<_Ret, _Args...>(this, name, fn);
functions.addSymbol(name.c_str(), new_func);
return *this;
}
And LuaGlueFunction happens to look like this:
template<typename _Ret, typename... _Args>
class LuaGlueFunction : public LuaGlueFunctionBase
{
public:
typedef _Ret ReturnType;
typedef _Ret (*MethodType)( _Args... );
LuaGlueFunction(LuaGlueBase *lg, const std::string &n, MethodType fn) :
g(lg), name_(n), fn_(std::forward<decltype(fn)>(fn))
{ }
~LuaGlueFunction() {}
std::string name() { return name_; }
bool glue(LuaGlueBase *luaGlue)
{
lua_pushlightuserdata(luaGlue->state(), this);
lua_pushcclosure(luaGlue->state(), &lua_call_func, 1);
//printf("add function: %s\n", name_.c_str());
lua_setglobal(luaGlue->state(), name_.c_str());
return true;
}
int invoke(lua_State *state)
{
ReturnType ret = applyTuple(g, state, fn_, args);
lua_pop(state, Arg_Count_);
stack<_Ret>::put(g, state, ret);
return 1;
}
private:
LuaGlueBase *g;
std::string name_;
MethodType fn_;
std::tuple<_Args...> args;
static const unsigned int Arg_Count_ = sizeof...(_Args);
static int lua_call_func(lua_State *state)
{
auto mimp = (LuaGlueFunction<_Ret, _Args...> *)lua_touserdata(state, lua_upvalueindex(1));
return mimp->invoke(state);
}
};
I'm attempting to allow the detection of an array, and then autobox it in a LuaGlueStaticArray type internally (that part already works, assuming I can keep the array from decaying into a pointer).
Hopefully that helps explain a little better what I'm trying to do.
There's a problem with the call function template. It needs to be defined as
template<typename _Ret, typename... Args>
static _Ret call(_Ret (*fp)(Args...), Args &&... args)
// ^^^ no &&
You want perfect forwarding for the arguments you pass in, but you do no want to force the types of the function parameters to reference types.
Next, when you pass an array to a function it decays to a pointer to the address of the first element. So your function foo is actually equivalent to
int foo(int *arr) // size information is lost
Keeping this in mind, you do not want arr to be deduced as int (&)[4] when you pass it to call, so you must pass a pointer.
call<int>(foo_ptr, &arr[0]); // pass a pointer to the beginning
After making these changes your code works. Live demo
If you want to preserve the array's size when passing it to foo, change that function to
int foo(int (&arr)[4])
{ ... }
And then call it as
decltype(foo)* foo_ptr = &foo;
call<int>(foo_ptr, arr);
As mpark points out in the comments, in both examples above there's no need to explicitly mention the return type of call, or form the function pointer foo_ptr. The calls can simply be
call(foo, &arr[0]); // with int foo(int *arr)
or
call(foo, arr); // with int foo(int (&arr)[4])
Live demo

How to reimplement this with std algorithms?

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!

template argument deduction for pointer to member function?

I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation.
I have the following code which works exactly how I want it to:
#include <iostream>
namespace thr {
template<typename T, T func>
struct delegate;
template<typename R,
typename C,
typename... A,
R (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{
delegate(C* obj_)
: _obj(obj_)
{}
R operator()(A... a)
{
return (_obj->*mem_fun)(a...);
}
private:
C* _obj;
};
} // namespace thr
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;
cb c(&f);
std::cout << c(4, 3);
return 0;
}
However, the usage is not very elegant:
thr::delegate<decltype(&foo::bar), &foo::bar>
I would like to use a function template which deduces the template parameters and returns a delegate instance; something along the lines of (this code does not compile):
template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
return thr::delegate<decltype(func), func>(obj);
}
This would allow for more elegant syntax:
auto cb = bind(&foo::bar, &f);
Is it possible to deduce a non-type parameter in a function template?
Is what I'm trying to achieve even possible?
Would std::function help? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close.
I think the compiler supplied STL does pretty horrible things to make it work smoothly. You may want to have a look at as an example before giving up.
Edit: I went out and tried what you try to accomplish. My conclusion is a compile error:
The return type of the bind (delegate) must name the pointer to member because it is your own requirement.
bind should accept the name of the pointer to member to be elegant (i.e. your requirement)
Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type.
Therefore one of your requirements must go.
Edit 2: I took the liberty of changing your delegate so bind works as you wish. bind might not be your priority though.
#include <iostream>
namespace thr {
template<typename C,typename R,typename... A>
struct delegate
{
private:
C* _obj;
R(C::*_f)(A...);
public:
delegate(C* obj_,R(C::*f)(A...))
: _obj(obj_),_f(f)
{}
R operator()(A... a)
{
return (_obj->*_f)(a...);
}
};
} // namespace thr
template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
return thr::delegate<C,R,A...>(obj,f);
}
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
auto c = bind(&foo::bar, &f);
std::cout << c(4, 6);
return 0;
}
It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters.
Given:
template <size_t I> struct Integral { static size_t const value = I; };
You can have:
template <size_t N>
Integral<N> foo(char const (&)[N]);
But you cannot have:
Integral<N> bar(size_t N);
In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. It can be noticed that in the former case, N appeared in the template parameters list of the type signature.
Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature.
There may be a saving grace using constexpr, which can turn a regular value into a constant fit for template parameters:
constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }
Integral<fib(4)> works;
But I am not savvy enough to go down that road...
I do however have a simple question: why do you think this will speed things up ? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. Are you sure it's worth sweating over this ?