Function passed as template argument - c++

I'm looking for the rules involving passing C++ templates functions as arguments.
This is supported by C++ as shown by an example here:
void add1(int &v) { v += 1 }
void add2(int &v) { v += 2 }
template <void (*T)(int &)>
void doOperation()
{
int temp = 0;
T(temp);
std::cout << "Result is " << temp << std::endl;
}
int main()
{
doOperation<add1>();
doOperation<add2>();
}
Learning about this technique is difficult, however. Googling for "function as a template argument" doesn't lead to much. And the classic C++ Templates The Complete Guide surprisingly also doesn't discuss it (at least not from my search).
The questions I have are whether this is valid C++ (or just some widely supported extension).
Also, is there a way to allow a functor with the same signature to be used interchangeably with explicit functions during this kind of template invocation?
The following does not work in the above program, at least in Visual C++, because the syntax is obviously wrong. It'd be nice to be able to switch out a function for a functor and vice versa, similar to the way you can pass a function pointer or functor to the std::sort algorithm if you want to define a custom comparison operation.
struct add3 {
void operator() (int &v) {v += 3;}
};
...
doOperation<add3>();
Pointers to a web link or two, or a page in the C++ Templates book would be appreciated!

Yes, it is valid.
As for making it work with functors as well, the usual solution is something like this instead:
template <typename F>
void doOperation(F f)
{
int temp = 0;
f(temp);
std::cout << "Result is " << temp << std::endl;
}
which can now be called as either:
doOperation(add2);
doOperation(add3());
See it live
The problem with this is that if it makes it tricky for the compiler to inline the call to add2, since all the compiler knows is that a function pointer type void (*)(int &) is being passed to doOperation. (But add3, being a functor, can be inlined easily. Here, the compiler knows that an object of type add3 is passed to the function, which means that the function to call is add3::operator(), and not just some unknown function pointer.)

Template parameters can be either parameterized by type (typename T) or by value (int X).
The "traditional" C++ way of templating a piece of code is to use a functor - that is, the code is in an object, and the object thus gives the code unique type.
When working with traditional functions, this technique doesn't work well, because a change in type doesn't indicate a specific function - rather it specifies only the signature of many possible functions. So:
template<typename OP>
int do_op(int a, int b, OP op)
{
return op(a,b);
}
int add(int a, int b) { return a + b; }
...
int c = do_op(4,5,add);
Isn't equivalent to the functor case. In this example, do_op is instantiated for all function pointers whose signature is int X (int, int). The compiler would have to be pretty aggressive to fully inline this case. (I wouldn't rule it out though, as compiler optimization has gotten pretty advanced.)
One way to tell that this code doesn't quite do what we want is:
int (* func_ptr)(int, int) = add;
int c = do_op(4,5,func_ptr);
is still legal, and clearly this is not getting inlined. To get full inlining, we need to template by value, so the function is fully available in the template.
typedef int(*binary_int_op)(int, int); // signature for all valid template params
template<binary_int_op op>
int do_op(int a, int b)
{
return op(a,b);
}
int add(int a, int b) { return a + b; }
...
int c = do_op<add>(4,5);
In this case, each instantiated version of do_op is instantiated with a specific function already available. Thus we expect the code for do_op to look a lot like "return a + b". (Lisp programmers, stop your smirking!)
We can also confirm that this is closer to what we want because this:
int (* func_ptr)(int,int) = add;
int c = do_op<func_ptr>(4,5);
will fail to compile. GCC says: "error: 'func_ptr' cannot appear in a constant-expression. In other words, I can't fully expand do_op because you haven't given me enough info at compiler time to know what our op is.
So if the second example is really fully inlining our op, and the first is not, what good is the template? What is it doing? The answer is: type coercion. This riff on the first example will work:
template<typename OP>
int do_op(int a, int b, OP op) { return op(a,b); }
float fadd(float a, float b) { return a+b; }
...
int c = do_op(4,5,fadd);
That example will work! (I am not suggesting it is good C++ but...) What has happened is do_op has been templated around the signatures of the various functions, and each separate instantiation will write different type coercion code. So the instantiated code for do_op with fadd looks something like:
convert a and b from int to float.
call the function ptr op with float a and float b.
convert the result back to int and return it.
By comparison, our by-value case requires an exact match on the function arguments.

Function pointers can be passed as template parameters, and this is part of standard C++
. However in the template they are declared and used as functions rather than pointer-to-function. At template instantiation one passes the address of the function rather than just the name.
For example:
int i;
void add1(int& i) { i += 1; }
template<void op(int&)>
void do_op_fn_ptr_tpl(int& i) { op(i); }
i = 0;
do_op_fn_ptr_tpl<&add1>(i);
If you want to pass a functor type as a template argument:
struct add2_t {
void operator()(int& i) { i += 2; }
};
template<typename op>
void do_op_fntr_tpl(int& i) {
op o;
o(i);
}
i = 0;
do_op_fntr_tpl<add2_t>(i);
Several answers pass a functor instance as an argument:
template<typename op>
void do_op_fntr_arg(int& i, op o) { o(i); }
i = 0;
add2_t add2;
// This has the advantage of looking identical whether
// you pass a functor or a free function:
do_op_fntr_arg(i, add1);
do_op_fntr_arg(i, add2);
The closest you can get to this uniform appearance with a template argument is to define do_op twice- once with a non-type parameter and once with a type parameter.
// non-type (function pointer) template parameter
template<void op(int&)>
void do_op(int& i) { op(i); }
// type (functor class) template parameter
template<typename op>
void do_op(int& i) {
op o;
o(i);
}
i = 0;
do_op<&add1>(i); // still need address-of operator in the function pointer case.
do_op<add2_t>(i);
Honestly, I really expected this not to compile, but it worked for me with gcc-4.8 and Visual Studio 2013.

In your template
template <void (*T)(int &)>
void doOperation()
The parameter T is a non-type template parameter. This means that the behaviour of the template function changes with the value of the parameter (which must be fixed at compile time, which function pointer constants are).
If you want somthing that works with both function objects and function parameters you need a typed template. When you do this, though, you also need to provide an object instance (either function object instance or a function pointer) to the function at run time.
template <class T>
void doOperation(T t)
{
int temp=0;
t(temp);
std::cout << "Result is " << temp << std::endl;
}
There are some minor performance considerations. This new version may be less efficient with function pointer arguments as the particular function pointer is only derefenced and called at run time whereas your function pointer template can be optimized (possibly the function call inlined) based on the particular function pointer used. Function objects can often be very efficiently expanded with the typed template, though as the particular operator() is completely determined by the type of the function object.

The reason your functor example does not work is that you need an instance to invoke the operator().

Came here with the additional requirement, that also parameter/return types should vary.
Following Ben Supnik this would be for some type T
typedef T(*binary_T_op)(T, T);
instead of
typedef int(*binary_int_op)(int, int);
The solution here is to put the function type definition and the function template into a surrounding struct template.
template <typename T> struct BinOp
{
typedef T(*binary_T_op )(T, T); // signature for all valid template params
template<binary_T_op op>
T do_op(T a, T b)
{
return op(a,b);
}
};
double mulDouble(double a, double b)
{
return a * b;
}
BinOp<double> doubleBinOp;
double res = doubleBinOp.do_op<&mulDouble>(4, 5);
Alternatively BinOp could be a class with static method template do_op(...), then called as
double res = BinOp<double>::do_op<&mulDouble>(4, 5);
EDIT
Inspired by comment from 0x2207, here is a functor taking any function with two parameters and convertible values.
struct BinOp
{
template <typename R, typename S, typename T, typename U, typename V> R operator()(R (*binaryOp )(S, T), U u, V v)
{
return binaryOp(u,v);
}
};
double subD(double a, int b)
{
return a-b;
}
int subI(double a, int b)
{
return (int)(a-b);
}
int main()
{
double resD = BinOp()(&subD, 4.03, 3);
int resI = BinOp()(&subI, 4.03, 3);
std::cout << resD << std::endl;
std::cout << resI << std::endl;
return 0;
}
correctly evaluates to double 1.03 and int 1

Edit: Passing the operator as a reference doesnt work. For simplicity, understand it as a function pointer. You just send the pointer, not a reference.
I think you are trying to write something like this.
struct Square
{
double operator()(double number) { return number * number; }
};
template <class Function>
double integrate(Function f, double a, double b, unsigned int intervals)
{
double delta = (b - a) / intervals, sum = 0.0;
while(a < b)
{
sum += f(a) * delta;
a += delta;
}
return sum;
}
.
.
std::cout << "interval : " << i << tab << tab << "intgeration = "
<< integrate(Square(), 0.0, 1.0, 10) << std::endl;

Related

Extract type of input parameter in templated function taking a function as parameter

I have this function:
template<typename T, int (*F)(T&)>
void DoStuff(T& s)
{
auto an = make_any<T>(s);
cout << _GetDataFromAny<MyStruct, F>(an);
}
Which needs to be called like this:
DoStuff<MyStruct, Fun>(s);
This works fine, however I don't like having to specify the first type, since it is part of the signature of the second parameter. I would like to be able to deduce it such that I can just call:
DoStuff<Fun>(s);
However, I don't know how to specify in the template that the type T needs to be deduced from the signature of the function F.
Is this possible?
You can write a helper that deduces the argument type of a function pointer that returns int:
template<typename T>
T arg_type(int(*)(T&));
and then rewrite your function template slightly to take in a function pointer as a non-type template parameter, and figure out the argument type from that
template<auto F, typename T = decltype(arg_type(F))>
void DoStuff(T& s) {
// ...
}
Disclaimer: This answer went through a series of edits and corrections, many thanks goes to Jarod42 for his patience and help, and cigien for fruitful discussion. It is a bit longer than necessary, but I felt it is worth to keep a bit of the history. It is: the most simple / the one I would prefer / some explanation of the previous confusion. For a quick answer, read the second part.
The simple
You can use an auto template parameter (since C++17) for the function pointer and let T be deduced from the argument:
template<auto F, typename T>
void DoStuff(T& s)
{
int x = F(s);
}
int foo(double&){ return 42;}
int main() {
double x;
DoStuff<&foo>(x);
}
Live Demo
The "right"
The downside of the above is that F and T are "independent". You can call DoStuff<&foo>(y) with eg a std::string y; and instantiation will only fail when calling F. This might lead to a unnecessarily complex error message, depending on what you actually do with F and s. To trigger the error already at the call site when a wrong T is passed to a DoStuff<F> you can use a trait to deduce the argument type of F and directly use that as argument type of DoStuff:
template <typename T> struct param_type;
template <typename R,typename P>
struct param_type< R(*)(P&)> {
using type = P;
};
template<auto F>
void DoStuff(typename param_type<decltype(F)>::type& s)
{
int x = F(s); // (1)
}
int foo(double&){ return 42;}
int main() {
double x;
DoStuff<foo>(x);
std::string y;
DoStuff<foo>(y); // (2) error
}
Now the error that before would only happen inside the template (1) happens already in main (2) and the error message is much cleaner.
Live Demo
The "wrong"
Mainly as curiosity, consider this way of deducing the parameter type from the function pointer:
template <typename T> struct param_type;
template <typename R,typename P>
struct param_type< R(*)(P&)> {
using type = P;
};
template<auto F, typename T = typename param_type<decltype(F)>::type>
void DoStuffX(T& s)
{
}
int foo(double&){ return 42;}
int main() {
double x;
DoStuffX<foo>(x);
}
This was my original answer, but it was not actually doing what I thought it was doing. Note that I was not actually calling F in DoStuff and to my surprise this compiled:
int main() {
std::string x;
DoStuffX<foo>(x);
}
The reason is that the default template argument is not used when T can be decuded from the passed parameter (see here). That is, DoStuffX<foo>(x); actually instantiates DoStuffX<foo,std::string>. We can still get our hands on the default via:
int main() {
std::string x;
auto f_ptr = &DoStuffX<foo>;
f_ptr(x); // error
}
Now calling DoStuffX<foo> with a std::string is a compiler error, because here DoStuffX<foo> is instantiated as DoStuffX<foo,double>, the default argument is used (there is no parameter that could be used to deduce T when DoStuffX is instantiated).

How to define a new function from an existed template function in C++

Recently I am learning the template function in C++. I am wondering if there is any simple way for me to do the following thing.
For example, I have defined a template function in C++ as follow:
template <typename T, float t_p>
void func_a(T* input, T* output):
{
output = input / t_p;
}
Now, I want to define another template function based on this template function for f_p = 4.0. I know I may be able to do the following thing:
template <typename T>
void func_b(T* input, T* output):
{
func_a<T,4.0>(input, output);
}
but this code looks very heavy. Especially when I have many input variables. I am wondering if there is any way that I can do to be similar as follows
template <typename, T>
func_b = func_a<T , 4.0>;
If so, it will be very helpful
You can't do it with functions, but you can do it with functors. S.M. noted that you can't use float as a template non-type parameter, so let's replace it with int. I also suppose that you want to operate on values, not on pointers (either dereference pointers, or use references).
template<int t_p>
struct func_a
{
template<typename T>
void operator()(const T& input, T& output) const
{
output = input / t_p;
}
};
using func_b = func_a<4>;
using func_c = func_a<5>;
Now you can use these functors in the following way:
void foo()
{
int a = 100;
int b;
func_a<2>()(a, b);
func_b()(a, b);
func_c()(a, b);
}
Note that you need extra empty parentheses to create a functor.
If you want to use float you can do something like this:
struct func_a
{
func_a(float p) : p(p) { }
template<typename T>
void operator()(const T& input, T& output) const
{
output = input / p;
}
private:
const float p;
};
void foo()
{
const auto func_b = func_a(4);
const auto func_c = func_a(5);
float a = 100;
float b;
func_a(2)(a, b);
func_b(a, b);
func_c(a, b);
}
Maybe a little Off Topic but I give you a useful, I hope, little suggestion: switch the order of your template parameters.
I mean: write func_a() as follows (I use int for t_p because, as pointed by S.M., a float value can't a valid template parameter)
template <int t_p, typename T>
void func_a(T* input, T* output):
{ output = input / t_p; }
The point is that T can be deduced from the function arguments (input and output) where t_p can't be deduced so must be explicated.
If the order is T first and t_p second, you must explicate also T, so (by example) in func_b() you must write
func_a<T,4>(input, output);
If the order is t_p first and T second, you must explicate only t_p and you can let the compiler deduce the T type; so you can simply write
func_a<4>(input, output);
In this case is a little improvement but, in other circumstances, can be useful.

call template function with async

need to run a function asynchronously, when function takes template argument. Code below does not compile, any help?
template<typename T>
void say(int n, T t) {
cout << " say: " << n << " " << t << endl;
}
template<typename F, typename... Ts>
inline auto reallyAsync(F&& f, Ts&&... params){
return std::async(
std::launch::async,
std::forward<F>(f),
std::forward<Ts>(params)...);
}
int main() {
int n = 10; float x = 100;
say(n, x); // works
reallyAsync(&say, n, x) ; // does not work
}
say is a function-template, you cannot take the address of a function-template because its not yet a function (see comments):
int main() {
int n = 10; float x = 100;
say(n, x); // works because of template argument deduction
reallyAsync(&say, n, x); //fails because say isn't a resolved function.
}
you can however, pass an instantiation of say:
int main() {
int n = 10; float x = 100;
say(n, x); // works
reallyAsync(&say<decltype(x)>, n, x);
}
Outputs:
say: 10 100
say: 10 100
Live Example
Basically, say is not a function, it is a function template. You cannot get an address of a template with &.
Just change:
reallyAsync(&say, n, x)
to:
reallyAsync(&say<float>, n, x)
and it should work.
reallyAsync(&say, n, x)
say is a template. In C++, you can't take an address of a template. This is a meaningless proposition.
It is important to understand the difference between a template, and a template instance. A template is nothing more than a specification, of sorts. It doesn't exist in any real or meaningful term. And the address-of operator can only work with real, actual objects, that exist somewhere, in some-fashion.
To eliminate the compilation error, you'll have to instantiate the template, turning it into something tangible:
reallyAsync(&say<float>, n, x);
From your point of view this may not be ideal, and defeats the purpose of template functions. There's probably a better, different way to do whatever you're really trying to accomplish, that does not require explicit template instantiation.

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

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 ?