Assign generic function to function pointer struct memeber - c++

I have to assign the following member of a struct:
esp_err_t (*handler)(httpd_req_t *r);
As you can see, it is a function pointer. I have a generic template function that I would like to assign as handler:
template <class Tmsg>
esp_err_t HandleRpc(httpd_req_t *req){...}
I am assigning the handler member inside a generic template class, so I have a generic type argument Tpayload:
httpd_uri_t cfg = {
...
.handler = HandleRpc<Tpayload>,
...
};
I get:
expected primary-expression before '>' token
The issue lies in the fact that I can't pass a member method pointer (I.E. esp_err_t (RpcServer::*)(...)), but RpcServer is a generic template class (I.E. has a template with one generic parameter). So I thought that by creating a generic template function outisde the class (global scope?), and passing the RpcServer instance into that function, I would be able to retrieve my instance of RpcServer<T> and all would be well.
Here is the smallest amount of code I could come up with to reproduce the issue:
int main()
{
}
template <class T>
class RpcServer{
public:
void RegisterHandler();
};
struct HandlerInfo{
void (*handler)();
};
template <class T>
void Handle(RpcServer<T> test)
{
}
template <class T>
void RpcServer<T>::RegisterHandler(){
HandlerInfo info = {
.handler = Handle<T>;
};
}
Am I missing the obvious, or is what I am trying to do going to require some uglier trickery?

struct HandlerInfo{
void (*handler)();
};
handler is a pointer to a function that takes no parameters, and doesn't return anything. You can set this pointer to point to any function. As long as it takes no parameters, and doesn't return anything (its return type is void). There are no exceptions to this, this is how C++ works, it is a strongly-typed language.
template <class T>
void Handle(RpcServer<T> test)
{
This is a template for a function that takes one parameter. The type of the parameter is not material. The point is that every instance of this template will be a function that takes exactly one parameter, always.
In C++, a pointer to a function that has no parameters can only be set to point to such a function. You cannot set this function pointer to point to a function that takes one parameter, or two parameters, or ten parameters. It can only be set to a function that takes exactly zero parameters. That's because that's what the pointer points to.
If you were to change the template function so that it takes no parameters, then this would work, of course:
int main()
{
}
template <class T>
class RpcServer{
public:
void RegisterHandler();
};
struct HandlerInfo{
void (*handler)();
};
template <class T>
void Handle()
{
}
template <class T>
void RpcServer<T>::RegisterHandler(){
HandlerInfo info = {
.handler = Handle<T>
};
}
This compiles on gcc 10. ".member" initialization syntax has been supported by gcc for a long time, but it's only been standardized as of C++20, so other compilers may not support this syntax.
You could, if you wish, declare this to be a pointer to a function that takes an RpcServer<int> as its parameter:
struct HandlerInfo{
void (*handler)(RpcServer<int>);
};
Now, you will be able to initialize it to point to such a function:
HandlerInfo info = {
.handler = Handle<int>
};
HandleInt instantiates a function that takes such a parameter, so the types match exactly.
Or, alternatively, make HandlerInfo itself a matching template:
template <class T>
class RpcServer{
public:
void RegisterHandler();
};
template<class T>
struct HandlerInfo{
void (*handler)(RpcServer<T>);
};
template <class T>
void Handle(RpcServer<T> )
{
}
template <class T>
void RpcServer<T>::RegisterHandler(){
HandlerInfo<T> info = {
.handler = Handle<T>
};
}
int main()
{
RpcServer<int> server;
server.RegisterHandler();
}
(Note -- your code has other syntax errors; if they were fixed it would seem that, at first, the code would compie; but if an attempt was made to instantiate the templates, it would fail due to the type mismatch)

Related

Class Template specialization for multiple types

I found a few questions that ask something similar but could not find a straight answer for my particular case.
The whole syntax for Templates is very confusing to me so I may just misunderstood something.
I have a class template that is supposed to accept every type.
Simple example:
template <class T>
class State {
public:
void set(T newState);
T get();
private:
T state;
};
template <class T>
void State<T>::set(T newState){
state = newState;
}
template <class T>
T State<T>::get(){
return state;
}
Now I would like to have a specialised template for a group of types that adds an additional function for these types. From what I found out so far I can utilize so called type_traits but how exactly they are used to achieve this is still a mystery to me.
F.e. this specialization for the int type but instead of writing this just for the int type I would also like to allow all other int and float variants. I found std::is_arithmetic but have no Idea how to utilize it to achieve this.
template <>
class State <int> {
public:
void set(int newState);
int get();
int multiplyState(int n);
private:
int state;
};
void State<int>::set(int newState){
state = newState;
}
int State<int>::get(){
return state;
}
int State<int>::multiplyState(int n){
return state*n;
}
You can use partial template specialization in combination with SFINAE to achieve this:
#include <type_traits>
template <class T, typename = void>
class State
{
T state;
public:
void set(T newState)
{
state = newState;
}
T get()
{
return state;
}
};
template <typename T>
class State<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{
T state;
public:
void set(int newState)
{
state = newState;
}
int get()
{
return state;
}
int multiplyState(int n)
{
return state*n;
}
};
live example here
The trick here lies in the use of the second template parameter (which can be unnamed and is given a default argument). When you use a specialization of your class template, e.g., State<some_type>, the compiler has to figure out which of the templates should be used. To do so, it has to somehow compare the given template arguments with each template and decide which one is the best match.
The way this matching is actually done is by trying to deduce the arguments of each partial specialization from the given template arguments. For example, in the case of State<int>, the template arguments are going to be int and void (the latter is there because of the default argument for the second parameter of the primary template). We then try to deduce the arguments for our sole partial specialization
template <typename T>
class State<T, std::enable_if_t<std::is_arithmetic_v<T>>>;
from the template arguments int, void. Our partial specialization has a single parameter T, which can directly be deduced from the first template argument to be int. And with that, we're already done as we have deduced all parameters (there is only one here). Now we substitute the deduced parameters into the partial specialization: State<T, std::enable_if_t<std::is_arithmetic_v<T>>>. We end up with State<int, void>, which matches the list of initial arguments of int, void. Therefore, the partial template specialization applies.
Now, if, instead, we had written State<some_type>, where some_type is not an arithmetic type, then the process would be the same up to the point where we have successfully deduced the parameter for the partial specialization to be some_type. Again, we substitute the parameter back into the partial specialization State<T, std::enable_if_t<std::is_arithmetic_v<T>>>. However, std::is_arithmetic_v<some_type> will now be false, which will lead to std::enable_if_t<…> not being defined and substitution fails. Since substituion failure is not an error in this context, this simply means that the partial specialization is not an option here and the primary template will be used instead.
If there were multiple matching partial specializations, they then would have to be ranked to pick the best match. The actual process is quite complicated, but it generally boils down to picking the most concrete specialization.
While for a small example like this it's fine to specialize the whole class, in more complicated cases you might be interested in avoiding having to duplicate all the members just so you can add one member to the specialization. To that end, a common technique is to inherit the extra member functions from a public base class, and specialize only the base class to either have or not have the members. You have to use CRTP so that the base class member functions know how to access the derived class. This looks like:
// StateBase only contains the extra multiplyState member when State tells it to
// define it, based on T being an arithmetic type
template <class D, class T, bool has_multiply>
struct StateBase {};
template <class D, class T>
struct StateBase<D, T, true> {
T multiplyState(int n) {
return static_cast<D*>(this)->state * n;
}
};
template <class T>
class State : public StateBase<State<T>, T, std::is_arithmetic<T>::value> {
public:
// no need to duplicate these declarations and definitions
void set(T newState);
T get();
private:
// note that we write State::StateBase to force the injected-class-name to be found
friend struct State::StateBase;
T state;
};
Coliru link

How can I use a nested type belonging to a templated class in another template function in C++?

I'm setting up a function that initializes tuples based on a tuple type and a functor struct For that has a size_t template argument INDEX to retain the compile-time index. This functor may also depend on other template arguments T.... Because of this the functors exist within other structures (TClass in this example) that hold these template arguments.
The initialization function (called Bar here) has a template<std::size_t> class template argument to ensure that the used class actually can store the index.
While the design I've come up with works fine when I call it from a non-template function, it does not compile if the template T2 of a function does determine the template parameter of the wrapper TClass.
Here is the definition of the functor For wrapped inside TClass:
#include <cstdlib>
template <typename T> struct TClass {
template<std::size_t INDEX> struct For {
void operator()() {}
};
};
And here are the function calls i want to use:
template <template<std::size_t> class FOR> void bar() {
//...
}
template <typename T> void foo() {
bar<TClass<T>::For>(); //Does not compile
}
int main() {
bar<TClass<int>::For>(); //Works
foo<int>();
return 0;
}
The compiler output for the faulty foo-call is:
error: dependent-name ‘TClass<T>::For’ is parsed as a non-type, but instantiation yields a type
Bar<TClass<T>::For>(); //Does not compile
I know that dependent type names usually have to be preceded by a typename but this is also not necessary for the first bar-call. I assumed it was because the template argument can only be interpreted as a type. So I thought that maybe typename would result in correct compilation but if I change foo to
template <typename T> void foo() {
bar<typename TClass<T>::For>(); //Does not compile
}
I get:
error: ‘typename TClass<int>::For’ names ‘template<long unsigned int INDEX> struct TClass<int>::For’, which is not a type
Bar<typename TClass<T>::For>(); //Does not compile
I've also come up with a design where the ()-operator of TClass depends on the template INDEX which also works fine because it is not necessary to use nested types anymore. It looks like this:
#include <cstdlib>
template <typename T> struct TClass {
template<std::size_t INDEX> void operator()() {}
};
template <typename FOR> void bar() {
//...
}
template <typename T> void foo() {
bar<TClass<T>>(); //Does compile
}
Apparently it is not possible to use dependent type names in functions where the template of the type is determined by the function's template parameters, but why? And how do I implement this correctly? To make writing future type checks with type traits easier I would prefer it if I can use a functor.
The compiler cannot know that TClass<T>::For refers to a template at the first stage of template instantiation. It needs a bit of help with template keyword. Fix:
template <typename T> void foo() {
bar<TClass<T>::template For>();
}

template function with no object arguments specialization

I'd like to specialize a template function to take non-pointer types and if in case it gets a pointer I'd like to call it without the *.
I'm wondering if there's a way without using std::remove_pointer.
for example I'd like to do something like this:
template<typename T>
void setName() {
name = __PRETTY_FUNCTION__;
}
template<typename T>
void setName<T*>() {
setName<T>();
}
name is defined as a private data member.
Your idea is correct but partial function template specialization is not allowed in C++. Fortuately partial class template specialization is allowed so you can use static method workaround (see specialization of setName_impl below) and if needed function template wrapper (see setName() below):
template<typename T>
struct setName_impl{
static void exec() { }
};
template<typename T>
struct setName_impl<T*>{
static void exec() {
setName<T>::exec();
}
};
template<typename T>
void setName() {
setName_impl<T>::exec();
}

Using template argument as template argument type

I seem to be unable to use multiple layers of templates in the following manner,
template <typename T>
template <T value>
void printValueAsInteger()
{
printf("value as integer is %i\n", (int) value);
}
so that it could be called as:
printValueAsInteger<123>();
It results in the following error message: too many template-parameter-lists.
It works if I use template <typename T, T value> with printValueAsInteger<int, 123>(), but that requires me to explicitly specify the type. How can I make it so that printValueAsInteger<123>() prints value as integer is 123?
edit:
I'll be more specific in what I need this for. My goal is to pass a member function as a function pointer, and I thought of wrapping it using templates:
template <typename T>
template <T* instance, void (T::*method)()>
void wrappedMethod()
{
(instance->*method)();
}
void callFunction(void (*function)())
{
(*function)();
}
and then pass it like this:
Base *instance = new Derived;
callFunction(&wrappedFunction<instance, Base::method>);
edit:
Err, I just realised that I probably shouldn't (and can't) use a runtime-defined variable as a template argument. I'm now trying to work around it using a class instantiated with the otherwise template arguments and creating a template function which uses that class. Or something like that. Nope, doesn't work.
Note that I cannot change the signature of callFunction, as it's part of a third party API.
At last!
I put the following in a header,
class Callable
{
public:
virtual ~Callable() { }
virtual void call() { }
};
typedef void (*functionPtr)();
extern unsigned nextMethodId;
extern functionPtr wrappedMethods[];
extern Callable *boundMethods[];
template <unsigned I>
class MethodWrapper
{
public:
static void function();
};
template <typename T>
class Method : public Callable
{
public:
Method(T* instance, void (T::*method)());
virtual void call();
private:
T* instance;
void (T::*method)();
};
template <typename T>
Method<T>::Method(T* instance, void (T::*method)())
: instance(instance), method(method) {
}
template <typename T>
void Method<T>::call()
{
if (instance && method)
(instance->*method)();
}
template <typename T>
static functionPtr bindMethod(T* instance, void (T::*method)())
{
boundMethods[nextMethodId] = new Method<T>(instance, method);
return (void (*)()) wrappedMethods[nextMethodId++];
}
and this in a source file:
#include "<insert header name here>.h"
unsigned nextMethodId = 0;
functionPtr wrappedMethods[] = {
&MethodWrapper<0>::function,
&MethodWrapper<1>::function,
&MethodWrapper<2>::function
};
Callable *boundMethods[sizeof(wrappedMethods) / sizeof(functionPtr)];
template <unsigned I>
void MethodWrapper<I>::function()
{
boundMethods[I]->call();
}
and I could use it like this:
Base *instance = new Derived;
void (*function)() = bindMethod(instance, &Base::method);
callFunction(function);
It successfully calls the derived instance's version of the method. Sadly, the amount of methods you are allowed to bind is fixed (three in this example), but it's easily extendable.
A simple transform is having the runtime value be an argument to the constructor of a functor that holds the instance pointer and the pointer to member function. The syntax at the place of use will change from:
Base *instance = new Derived;
callFunction(&wrappedFunction<instance, Base::method>);
To:
callFunction( WrappedFunction<Base,&Base::method>( instance ) );
The implementation of the WrappedFunction type is actually simple, so I leave it as an exercise. Note that a major change in this approach is that the argument to callFunction becomes a functor, and not a function pointer.
In C++11 (or with boost) the simplest way would be not coding anything and just use the available resources. Change the signature of callFunction to:
void callFunction( function<void ()> f );
And use bind to place the call:
callFunction( bind( &Base::method, instance ) );
For your first example, you can specify int as the type of template parameter:
template <int I>
void printValueAsInteger()
{
printf("value as integer is %i\n", I);
}
For your edit, you cannot use runtime-defined variables as you have already mentioned because templates are used at compile-time. Using std::bind and std::function would make it simple:
void callFunction(std::function<void()> f)
{
f();
}
Base *instance = new Derived;
callFunction(std::bind(&Base::method, instance));
After Comment
The only way I can think of is to make your member function static:
callFunction(&Base::method); // Okay if the method is declared static
Or use a global wrapper function with a global instance:
Base *instance = new Derived; // Global
void wrapperFunction()
{
instance->method();
}
callFunction(wrapperFunction);

How to pass a method pointer as a template parameter

I am trying to write a code that calls a class method given as template parameter. To simplify, you can suppose the method has a single parameter (of an arbitrary type) and returns void. The goal is to avoid boilerplate in the calling site by not typing the parameter type. Here is a code sample:
template <class Method> class WrapMethod {
public:
template <class Object>
Param* getParam() { return &param_; }
Run(Object* obj) { (object->*method_)(param_); }
private:
typedef typename boost::mpl::at_c<boost::function_types::parameter_types<Method>, 1>::type Param;
Method method_;
Param param_
};
Now, in the calling site, I can use the method without ever writing the type of the parameter.
Foo foo;
WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar;
foo_bar.GetParam()->FillWithSomething();
foo_bar.Run(foo);
So, this code works, and is almost what I want. The only problem is that I want to get rid of the BOOST_TYPEOF macro call in the calling site. I would like to be able to write something like WrapMethod<Foo::Bar> foo_bar instead of WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar.
I suspect this is not possible, since there is no way of referring to a method signature other than using the method signature itself (which is a variable for WrapMethod, and something pretty large to type at the calling site) or getting the method pointer and then doing typeof.
Any hints on how to fix these or different approaches on how to avoid typing the parameter type in the calling site are appreciated.
Just to clarify my needs: the solution must not have the typename Param in the calling site. Also, it cannot call FillWithSomething from inside WrapMethod (or similar). Because that method name can change from Param type to Param type, it needs to live in the calling site. The solution I gave satisfies both these constraints, but needs the ugly BOOST_TYPEOF in the calling site (using it inside WrapMethod or other indirection would be fine since that is code my api users won't see as long as it is correct).
Response:
As far as I can say, there is no possible solution. This boil down to the fact that is impossible to write something like WrapMethod<&Foo::Bar>, if the signature of Bar is not known in advance, even though only the cardinality is necessary. More generally, you can't have template parameters that take values (not types) if the type is not fixed. For example, it is impossible to write something like typeof_literal<0>::type which evalutes to int and typeof_literal<&Foo::Bar>::type, which would evaluate to void (Foo*::)(Param) in my example. Notice that neither BOOST_TYPEOF or decltype would help because they need to live in the caling site and can't be buried deeper in the code. The legitimate but invalid syntax below would solve the problem:
template <template<class T> T value> struct typeof_literal {
typedef decltype(T) type;
};
In C++0x, as pointed in the selected response (and in others using BOOST_AUTO), one can use the auto keyword to achieve the same goal in a different way:
template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar = GetWrapMethod(&Foo::Bar);
Write it as:
template <typename Object, typename Param, void (Object::*F)(Param)>
class WrapMethod {
public:
Param* getParam() { return &param_; }
void Run(Object* obj) { (obj->*F)(param_); }
private:
Param param_;
};
and
Foo foo;
WrapMethod<Foo, Param, &Foo::Bar> foo_bar;
foo_bar.getParam()->FillWithSomething();
foo_bar.Run(foo);
EDIT: Showing a template function allowing to do the same thing without any special template wrappers:
template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param))
{
Param param;
param.FillWithSomthing();
obj.*f(param);
}
and use it as:
Foo foo;
call(foo, &Foo::Bar);
2nd EDIT: Modifying the template function to take the initialization function as a parameter as well:
template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param), void (Param::*init)())
{
Param param;
param.*init();
obj.*f(param);
}
and use it as:
Foo foo;
call(foo, &Foo::Bar, &Param::FillWithSomething);
If your compiler supports decltype, use decltype:
WrapMethod<decltype(&Foo::Bar)> foo_bar;
EDIT: or, if you really want to save typing and have a C++0x compliant compiler:
template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar= GetWrapMethod(&Foo::Bar);
EDIT2: Although, really, if you want it to look pretty you either have to expose users to the intricacies of the C++ language or wrap it yourself in a preprocessor macro:
#define WrapMethodBlah(func) WrapMethod<decltype(func)>
Have you considered using method templates?
template <typename T> void method(T & param)
{
//body
}
Now the compiler is able to implicitly determine parameter type
int i;
bool b;
method(i);
method(b);
Or you can provide type explicitly
method<int>(i);
You can provide specializations for different data types
template <> void method<int>(int param)
{
//body
}
When you are already allowing BOOST_TYEPOF(), consider using BOOST_AUTO() with an object generator function to allow type deduction:
template<class Method> WrapMethod<Method> makeWrapMethod(Method mfp) {
return WrapMethod<Method>(mfp);
}
BOOST_AUTO(foo_bar, makeWrapMethod(&Foo::Bar));
Okay let's have a go at this.
First of all, note that template parameter deduction is available (as noted in a couple of answers) with functions.
So, here is an implementation (sort of):
// WARNING: no virtual destructor, memory leaks, etc...
struct Foo
{
void func(int e) { std::cout << e << std::endl; }
};
template <class Object>
struct Wrapper
{
virtual void Run(Object& o) = 0;
};
template <class Object, class Param>
struct Wrap: Wrapper<Object>
{
typedef void (Object::*member_function)(Param);
Wrap(member_function func, Param param): mFunction(func), mParam(param) {}
member_function mFunction;
Param mParam;
virtual void Run(Object& o) { (o.*mFunction)(mParam); }
};
template <class Object, class Param>
Wrap<Object,Param>* makeWrapper(void (Object::*func)(Param), Param p = Param())
{
return new Wrap<Object,Param>(func, p);
}
int main(int argc, char* argv[])
{
Foo foo;
Wrap<Foo,int>* fooW = makeWrapper(&Foo::func);
fooW->mParam = 1;
fooW->Run(foo);
Wrapper<Foo>* fooW2 = makeWrapper(&Foo::func, 1);
fooW2->Run(foo);
return 0;
}
I think that using a base class is the native C++ way of hiding information by type erasure.