template argument deduction for pointer to member function? - c++

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 ?

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

Implicit conversion to template

My example below suggests that implicit conversions from non-template types to template types won't work as seamlessly as those only involving non-template types. Is there a way to make them work nonetheless?
Example:
struct point;
template<unsigned d> struct vec {
vec() { }
// ...
};
template<> struct vec<2> {
vec() { }
vec(const point& p) { /* ... */ } // Conversion constructor
// ...
};
struct point {
operator vec<2>() { return vec<2>(/* ... */); } // Conversion operator
};
template<unsigned d> vec<d> foo(vec<d> a, vec<d> b) {
return vec<d>(/* ... */);
}
template<unsigned d1, unsigned d2>
vec<d1 + d2> bar(vec<d1> a, vec<d2> b) {
return vec<d1 + d2>(/* ... */);
}
int main(int argc, char** argv) {
point p1, p2;
vec<2> v2;
vec<3> v3;
foo(v2, p1);
foo(p2, v2);
foo(p1, p2);
bar(v3, p1);
}
Is there a way to let this code auto-convert from point to vec<2>?
I know I can overload foo and bar to allow for point arguments, delegating to the vec implementation using an explicit conversion. But doing this for all parameter combinations will become tedious, particularly for functions with many such parameters. So I'm not interested in solutions where I have to duplicate code for every parameter combination of every function.
It appears that neither the conversion constructor nor the cast operator are sufficient to achieve this. At least my gcc 4.7.1 reports no matching function call, although it does name the desired function in a notice, stating that ‘point’ is not derived from ‘vec<d>’.
There is no direct way to get the conversion from point to vec<2>, because at the time when the function call foo(v1,p1) is processed, a function foo that expects a vec<2> as second argument does not exist yet. It's just a function template, and in order for this to be instantiated to a foo(const vec<2> &,const vec<2> &), a function call with these exact argument types would have to be given.
In order for the code to work, the compiler would have to guess both how to instantiate the template parameters, and what type the point argument to convert to. This is too much in the general case (although in your particular code it appears simple, because there is no other possible way to interpret the intent of the programmer).
In terms of solving this, the only thing I can think of is to create highly templated conversion functions:
template <typename T>
struct make_vec
{ };
template <unsigned d>
struct make_vec<vec<d>>
{
static constexpr unsigned dim = d;
using type = vec<dim>;
static const type &from(const type &v)
{ return v; }
};
template <>
struct make_vec<point>
{
static constexpr unsigned dim = 2;
using type = vec<dim>;
static type from(const point &p)
{ return type(p); }
};
template <typename T>
typename make_vec<typename std::decay<T>::type>::type make_vec_from(T&& arg)
{ return make_vec<typename std::decay<T>::type>::from(std::forward<T>(arg)); }
And then implement the foo and bar functions as general templates (accepting all kinds of types, not only vec<d>, using make_vec defined above to convert the given types to the right kind of vec<d>):
namespace detail {
/* Your original implementation of foo. */
template<unsigned d> vec<d> foo(vec<d>, vec<d>) {
return vec<d>(/* ... */);
}
}
/* Templated version of foo that calls the conversion functions (which do
nothing if the argument is already a vec<d>), and then calls the
foo() function defined above. */
template <typename T, typename... Ts>
typename make_vec<typename std::decay<T>::type>::type foo(T&& arg, Ts&&... args)
{ return detail::foo(make_vec_from(arg),make_vec_from(args)...); }
In the case of bar you also need a way to calculate the return type, which is vec<d1+d2+d3...>. For this, a sum calculator is required, also templated:
template <typename... Ts>
struct dsum {
static constexpr unsigned value = 0;
};
template <typename T, typename... Ts>
struct dsum<T,Ts...> {
static constexpr unsigned value = make_vec<typename std::decay<T>::type>::dim + dsum<Ts...>::value;
};
Then, the return type of bar() is vec<dsum<T,Ts...>::value>.
A fully working example is here: http://liveworkspace.org/code/nZJYu$11
Not exactly simple, but might be worth it if you really have extremely many different combinations of arguments.

Any way to let the use of function pointers as template arguments easier?

I can use function pointer as template argument as the following
template<class R, class T, R (*Fun)(T)>
class MyClass;
Any way to make it is easy as
MyClass<&MyFun> a;
Here is a horrible answer, but I cannot think of a better one.
template<typename R, typename Arg, R(*Fun)(Arg)>
class MyClass {};
template<typename R, typename Arg>
struct MyClassHelper {
template<R(*Fun)(Arg)>
struct Class {
typedef MyClass<R, Arg, Fun> type;
};
};
template<typename R, typename Arg>
MyClassHelper<R, Arg> GetMyClass(R(*Fun)(Arg)); // no impl
void MyFun(int) {}
int main() {
typedef decltype( GetMyClass(&MyFun) ) A;
typedef A::Class<&MyFun> B;
typedef B::type a;
// or, in one line:
decltype( GetMyClass(&MyFun) )::Class<&MyFun>::type b;
}
which is ugly as sin. But at least it extracts the argument types of MyFun without repeating them...
It's not possible exactly as in the question, but yes it's possible if you flex your design a little bit. Let's take an example:
Suppose you have below function:
int foo (int i) { return i; }
Now you want to write:
MyClass<&foo> a; // instead of `Myclass<int, int, &foo> a;
Here how you will achieve it. First change the simple function:
int foo (int i) { return i; }
to encapsulated function object:
struct foo { // <--- function name here
int operator () (int i) { return i; } // <--- function body here
};
Both are almost same (in the case of function object an extra this pointer is passed which doesn't happen in the free function case):
int x = foo(2); // 1st case
int x = foo_(2); // 2nd case where `foo_` is an object of `struct foo`
Now you can use simply as you want!
template<class Func>
class MyClass {...}
MyClass<foo> a;
Here is a working demo.
There's already std::ptr_fun. With C++11, you can use it as
auto a = std::ptr_fun(&MyFun);
Update:
As the other attempts, and non attempts BTW, have shown, isn't it possible with your kind of template, least of all "as easy as" ;-). What you can do however, is sort of reimplement the existing standard template function pattern (std::ptr_fun, std::make_pair and the like) to return the desired type, if your main goal is "as easy as".

templated operator() overload C++

someone already asked this question, but the thread ended up with the original question not getting answered.
suppose you have this:
template<size_t i, class f_type>
void call_with_i(f_type f);
functor_type is either:
a) a struct with a method that has the following signature:
template<size_t i> operator()() const;
or, b) a function that looks like this:
template<size_t i> foo();
I want "call_with_i<42>(foo)" to be equivalent to "foo<42>()", but I can't figure out the right syntax to make that happen. I'd be satified with a solution that does just (a) but (a)+(b) would be great. I've already tried these syntaxes:
f< i >(); // doesn't work
f()< i >; // doesn't work
f.operator< i >(); // doesn't work
f.operator()< i >; // doesn't work
f.operator()< i >(); // works on msvc, but doesn't work on gcc.
How do you invoke operator() with explicit template arguments? Is there a way to invoke it in a way that the same syntax would also call a templated free function?
p.s. If you're wondering what i'm using this for, its because I'm writing a function repeat_to where repeat_to<10>(f) invokes f(0) then f(1) ... f(10). I'm using this to iterate through multiple boost::fusion vectors in parallel by index. yeah, i could use iterators, or i could just use a named member function, but i still want to know the answer.
edit note: i striked out stuff because passing a templated free function as an arg doesn't make any sense.
The member template is a dependent name, because its semantics depend on the type of f_type. That means you should put "template" before its name (to disambiguate the use of the "less-than" token), similar to how you should put typename before dependent qualified names:
template<size_t i, class f_type>
void call_with_i(f_type f) {
f.template operator()<i>();
// f.template foo<i>();
}
As a workaround, you may use a helper type:
template<size_t N> struct size_t_ { }; // or boost::mpl::int_
template<size_t i, class f_type>
void call_with_i(f_type f) {
f(size_t_<i>());
}
Now, you could define your operator() as follows:
template<size_t i> void operator()(size_t_<i>) const {
// i was deduced automatically by the function argument.
}
This comes handy for templated constructors, for which you cannot do f_type()<i>() or something. They will have to be deducible in that case.
In a case like yours I would use boost::function as functor type. You can then pass both function objects and function pointers while retaining the same interface.
#include <iostream>
template<size_t i, class f_type> void call_with_i(f_type f);
struct A {
template < size_t i >
void operator()() const {
/* no link err in demo */
}
template < size_t i >
void foo() {
/* no link err in demo */
}
};
int main(int argc, char * const argv[]) {
A f;
enum { Constant = 42 };
f.operator()<Constant>();
f.foo<Constant>();
return 0;
}
Is there a way to invoke it in a way that the same syntax would also call a templated free function?
Can you clarify? (pseudocode, or something)

functor generation from member function pointer type

I am trying to simplify (via make_fn()) the generation of functors that preprocess parameters (via wrap()) for member functions of arity n.
Generating the functors is basically working, but until now only by explicitly specifying the parameter types for the member function.
Now i'd like to generate the correct functor from the member function type it handles:
struct X {};
template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
bool wrap(C* c, X x)
{
return (c->*F)(process<T1>(x));
}
template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(F f) // <- problem here, F is not a type
{
return boost::bind(&wrap<C, T1, F>, _1, _2);
}
With this however, vc++ and g++ don't see F as a type for the parameter of make_fn(). I must miss something obvious here and am feeling somewhat blind.
The idea was that it should work like this:
struct A
{
bool f1(bool) { return true; }
};
void test()
{
A a;
X x;
make_fn(&A::f1)(&a, x);
}
Any ideas on how to make that work?
Background:
I have a fixed interface which, when simplified, looks like this:
bool invoke(C* c, const char* const functionName, int argCount, X* args);
X is a variant type which i have to convert to certain backend types (int, std::string, ...).
To handle these calls i have a map of functors that are looked up by name and map these calls to member functions of some instance.
The intention of the wrapping is to avoid manual conversions and instead generate functors which do the conversion for me or throw. I have this working with a macro based solution, but that solution requires to specify the types and the parameter count explicitly.
Via function overload resolution i hope to generate the correct converting functor implicitly from the member function signature.
It appears to me that you are attempting to turn a pointer passed to a function into a non-type template argument, which I'm afraid is not going to work (see comments to your question).
What you could do, is to store the function pointer in a function object. The following appears to compile:
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct X {};
template <class T>
bool process(X) { return true; }
template <class C, class T1, class Func>
struct wrap1
{
typedef bool result_type;
Func f;
wrap1(Func f): f(f) {}
bool operator()(C* c, X x)
{
return (c->*f)(process<T1>(x));
}
};
template<class C, typename T1>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(bool (C::*f)(T1))
{
return boost::bind(wrap1<C, T1, bool (C::*)(T1)>(f), _1, _2);
}
struct A
{
bool f1(bool) { return true; }
};
void test()
{
A a;
X x;
make_fn(&A::f1)(&a, x);
}
However, I'm not sure if that is any good and how you would create the rest of the wrappers. For the latter you might just get a compiler that supports variadic templates. :)