How do I create an array of function pointers of different prototypes? - c++

I have a few functions defined like this:
ParentClass* fun1();
ParentClass* fun2();
ParentClass* fun3(bool inp=false);
ChildClass* fun4();
ChildClass* fun5(int a=1, int b=3);
I would like to put them into an array of some kind as follows:
void* (*arr[5])() = {
(void* (*)())fun1,
(void* (*)())fun2,
(void* (*)())fun3,
(void* (*)())fun4,
(void* (*)())fun5
}
Now I would like to use this array of functions simply as
for(int i=0; i<5; i++)
someFunction(arr[i]());
Now I realize here that the issue is void* (*arr[5])(), but given that I only want to use the functions without supplying an argument, I would like all of these to be part of the same array.
These are very C-style ways to do it, though. Is there a better way to do it using Templates in C++?

C-style or not, what you have is straight undefined behaviour. Use lambdas:
void (*arr[5])() = {
[] { fun1(); },
[] { fun2(); },
[] { fun3(); },
[] { fun4(); },
[] { fun5(); }
};
These are okay because they perform the call through the function's correct type, and are themselves convertible to void (*)().
Forwarding the returned value stays simple enough, since the lambda provides a context for the conversion. In your case, since ChildClass supposedly inherits from ParentClass, an implicit conversion is enough:
ParentClass *(*arr[5])() = {
[]() -> ParentClass * { return fun1(); },
[]() -> ParentClass * { return fun2(); },
[]() -> ParentClass * { return fun3(); },
[]() -> ParentClass * { return fun4(); },
[]() -> ParentClass * { return fun5(); }
};

but given that I only want to use the functions without supplying an argument
It simply doesn't work like that. Did you ever wonder, then when you're putting function declarations in a header, why you have to write default parameters into the header and cannot place it in the definition in the implementation source file?
That's because the default parameters are in fact not "embedded" into the function, but used by the compiler to augment a function call with those parameters at a calling location, where those parameters are omitted. (EDIT: Also, as #Aconcagua so keenly observed in a comment, since default parameters are usually defined as part of a header function declaration, any change of the default values requires a full recompilation of any compilation unit that included those headers, ergo function declarations, for the change to actually take effect!)
While it's perfectly possible to do some really weird type casting madness to construct an array of function pointers like that, eventually you'll have to cast back to the original function call signature in order to not invoke undefined behavior.
If anything you'll have to bind the function pointer, together with a set of default parameters in some type that abstracts away the calling, does supply the parameters, and to the outside offers a polymorphic interface. So you'd have a std::vector<function_binder> or function_binder[] where function binder has an operator() that calls the function.
But when you're doing binding in the first place, you can bind it in an anonymous function, i.e. lambdas. At the time of lambda instantiation the default parameters are bound.
std::vector<void(*)()> fvec = {
[]{ func0(); },
[]{ func1(); },
[]{ func2(); }
};

You can use std::bind
std::function<ParentClass *(void)> arr[5] = {
std::bind(&fun1),
std::bind(&fun2),
std::bind(&fun3, false),
std::bind(&fun4),
std::bind(&fun5, 1, 3)
};
now you can do
for(int i=0; i<5; i++)
arr[i]();
You have to make sure every function parameter of all functions are bound.
This also works well with member functions. You just have to bind the object reference (e.g. this) as first parameter.

A c++20 solution:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return [](Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};
template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};
#define OVERLOADS_OF(...) \
generate_overloads< \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... ) ) \
>
which is a lot of boilerplate, but gets us:
ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
basically generate_overloads<x> takes a constexpr callable object x and lets you cast it at compile time to a pointer to a function of any compatible signature and call it with (almost) any signature.
Meanwhile, OVERLOADS_OF converts a function name into a constexpr object that does overload resolution on that function name. I use it here because fun3 as a function pointer does not know about its default arguments, but at overload resolution time it does.
In this particular case, it is far easier to just write toy lambdas to do this work; this is just an attempt to automate writing those toy lambdas for arbitrary compatible signatures.

Since you have tagged question with C++14 you should not use function pointers!
With C++14 you should prefer std::function and lambdas.
Also you should not use C style array, but only std::array and/or std::vector.
Also avoid raw pointers, use std::unique_ptr and std::shared_ptr.
So simplest and best way to solve it is:
std::array<std::function<ParentClass*()>,5> arr {
[]() { return fun1(); },
[]() { return fun2(); },
[]() { return fun3(true); },
[]() { return fun4(); },
[]() { return fun5(7, 9); }
};
Why not simple array of pointers like in #Quentin answer? He used lambdas, but he can't use lambda which binds anything (if you need to).

Related

How to declare the template argument for an overloaded function

I have a fairly big project that, regarding this question,
I can summarize with
this structure:
void do_something()
{
//...
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
All is working ok until someone (me) decides to reformat a little
minimizing some functions, rewriting
as this minimum reproducible example:
void do_something(const int a, const int b)
{
//...
}
void do_something()
{
//...
do_something(1,2);
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
And now the code doesn't compile with
error: no matching function for call
where use_funct is instantiated.
Since the error message was not so clear to me
and the changes were a lot I wasted a considerable
amount of time to understand that the compiler
couldn't deduce the template parameter
because do_something could now refer to
any of the overloaded functions.
I removed the ambiguity changing the function name,
but I wonder if there's the possibility to avoid
this error in the future not relying on template
argument deduction.
How could I specify in this case the template argument for do_something(), possibly without referring to a function pointer?
I haven't the slightest idea to express explicitly:
use_funct<-the-one-with-no-arguments->(do_something);
You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:
use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);
Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:
void do_something(int) {}
void do_something(double) {}
template<typename F> void use_funct(F funct) {
funct(1); // calls do_something(int)
funct(1.0); // calls do_something(double)
}
int main() {
use_funct([](auto x){ do_something (x); });
}
[...] possibly without referring to a function pointer?
I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:
using func_type = void();
use_funct<func_type>(do_something);

Get the name of a std::function

In the following toy-example, I would like to get the name of a function. The function itself was given as an std::function argument. Is it possible in C++ to get name of a std::function object?
void printName(std::function<void()> func){
//Need a function name()
std::cout << func.name();
}
void magic(){};
//somewhere in the code
printName(magic());
output: magic
Otherwise I would have to give the function's name as a second parameter.
No there isn't. Function names (like variable names) are compiled out so they are not visible at run-time.
Your best bet is to pass the name of the function (use a std::string or a const char*) as you've suggested yourself. (Alternatively you could base a solution on __func__ which was introduced in C++11.)
The answer is no, but you could make something like
template<class R, class... Args>
class NamedFunction
{
public:
std::string name;
std::function<R(Args...)> func;
NamedFunction(std::string pname, std::function<R(Args...)> pfunc) : name(pname), func(pfunc)
{}
R operator()(Args&&... a)
{
return func(std::forward<Args>(a)...);
}
};
And then define a preprocessor
#define NAMED_FUNCTION(var, type, x) NamedFunction<type> var(#x,x)
...
NAMED_FUNCTION(f, void(), magic);
Given a std::function it has a member function called target_type which returns the typeid of the stored function object. That means you can do
void printName(std::function<void()> func){
//Need a function name()
std::cout << func.target_type().name();
}
This returns an implementation-defined string that is unique for each type. With Visual Studio, this string is human-readable already. With gcc (or maybe it's glibc? I don't know who takes care of what in detail) you need to use abi::__cxa_demangle after including <cxxabi.h> to get a human-readable version of the type name.
EDIT
As Matthieu M. pointed out, given a function pointer, the type returned by this will just be the function's signature. For example:
int function(){return 0;}
printName(function);
This will output (assuming you demangled if necessary) int (*)() which is not the function's name.
This method will work with classes though:
struct Function
{
int operator()(){return 0;}
};
printName(Function{});
This will print Function as desired, but then doesn't work for function pointers.
You could also have your function with a string parameter for the name and then use a macro to call it
void _printName(std::function<void()> func, const std::string& funcName){
std::cout << funcName;
}
#define printName(f) _printName(f, #f)
void magic(){};
//somewhere in the code
printName(magic);
See example
Maintain your own map from function pointer to name.
template<class Sig>
std::map<Sig*, const char*>& name_map() {
static std::map<Sig*, const char*> r;
return r;
}
struct register_name_t {
template<class Sig>
register_name_t( Sig* sig, const char* name ) {
name_map()[sig]=name;
}
};
#define TO_STRING(A) #A
#define REGISTER_NAME(FUNC) \
register_name_t FUNC ## _register_helper_() { \
static register_name_t _{ FUNC, TO_STRING(FUNC) }; \
return _; \
} \
static auto FUNC ## _registered_ = FUNC ## _register_helper_()
Simply do REGISTER_NAME(magic); to register the name magic to the function magic. This should be done at file scope, either in a header or a cpp file.
Now we check if the std::function has a function pointer matching its signature stored inside of it. If so, we look it up in our name_map, and return the name if we find it:
template<class Sig>
std::string get_function_name( std::function<Sig> const& f ) {
auto* ptr = f.target<Sig*>();
if (!ptr) return {};
auto it = name_map().find(ptr);
if (it == name_map().end()) return {};
return it->second;
}
this is generally a bad idea.
I think the simplest solution is to use typeid(fun).name() for example like this:
#include <typeinfo>
#include <stdio.h>
void foobar( void )
{
}
int main()
{
printf( "%s\n", typeid( foobar ).name() );
return 0;
}
Now, it have a lot of drawbacks, and I would not recommend using that.
First of all, IIRC it shows the symbol of the function, not the name you used in source code.
Also, the name will change from compiler to compiler.
And finally, RTTI is slow.
[edit]
Also, I'm not sure how it works with std::function. Never used that, honestly.

How to curry a method on an object for passing it as a C-style callback?

Let's assume we have the following class A:
class A
{
public:
void sum(int x);
};
And we have a function f, which gets a C-style callback with one parameter of type int and calls it:
typedef void (*Callback)(int);
void f(Callback cb)
{
cb(5);
}
Is there any way in C++ to curry a method A::print on an object of type A and pass it to the function f? Something like this:
void main()
{
A a;
auto curry_a = ??; // something like curry_a = [&](int x) { a.sum(x) };
f(curry_a);
}
std::bind and lambda-function are not a solution, because they create objects of type std::function<> with overloaded operator(). It looks like currying in C++, but it cannot be used in my case. I need a real function pointer, i.e. generate code in real time.
You are out of luck, it can't be done in a satisfactory way: The only thing that is exactly a C-compatible function pointer is a function (or class-function but not instance function).
So, you'd have to create a function that fixes a parameter, like the this of a member function. The only way to set this parameter is through a global variable:
A *instance;
void (A::*a_fun)(int);
void applicator(int arg) { instance->*a_fun(arg); }
//...
int main() {
A a;
instance = &a;
a_fun = &A::sum;
f(applicator);
// ...
That is the only way to provide context to a plain function, through global variables.

C++ Functions with lambdas as arguments

I have an overload function, with the following signatures:
void Foo(const std::function<void(int )> &func);
void Foo(const std::function<void(int, int)> &func);
And when I want to use Foo() with lambdas, I'll have to do something like this:
Foo((std::function<void(int )>) [] (int i ) { /* do something */ });
Foo((std::function<void(int, int)>) [] (int i, int j) { /* do something */ });
Both of which are not so user-friendly. It'd be a lot easier to use the function without having to add the casting "(std::function<...>)" before the lambdas - like this:
Foo([] (int i ) { /* do something */ }); // executes the 1st Foo()
Foo([] (int i, int j) { /* do something */ }); // executes the 2nd Foo()
So, I need another overload, that accept lambda as its argument, and which automatically casts the lambda to one of the above signatures. How can this be done? Or, is it possible in the first place?
template <typename Function> void Foo(Function function) {
// insert code here: should be something like
// - check the signature of the 'function'; and
// - call 'Foo()' corresponding to the signature
}
Please help.
PS. I'm using VS2010.
If your lambda does not capture any variables—that is, it begins with []—then it is convertible to a function pointer, and you can declare Foo like so:
void Foo(void(*func)(int));
void Foo(void(*func)(int, int));
If you want to keep the std::function versions, you can have these versions forward to that one. If you don’t want to implement them separately, I think a variadic template would do nicely:
template<class... Args>
void Foo(void(*func)(Args...)) {
return std::function<void(Args...)>(func);
}
If your lambdas capture variables, then they’re not convertible to function pointers, and you’ll need to wrap them in std::function yourself.
Lambda's convert to std::function<> implicitly, there's no explicit conversion needed.
std::function<void(int, int)> func = [](int a, int b){ printf("Hello Lambda world!"); };
func(1, 2);
Ah, you're trying to get a const reference to it. Why though? You should be better off with a right-hand reference (as it's a temporary) or a copy. In both of those cases it should implicitly convert as well...

How to handle lambdas in a pre-lambda compiler

I have some code that can greatly be reduced in complexity by using lambdas. However unfortunately we have to use a compiler that does not fully support C++11 and we cannot easily switch. Now the question is how to keep the logic as close as possible to a lambda-expression with features not available (i.e. std::function is available, lambdas are not).
The usual solution is to define the functor somewhere else and then use it at the appropriate place:
struct functor{
functor( type & member ) : m_member( member ) {}
void operator()( ... ) {...}
type & m_member;
};
void function() {
use_functor( functor(...) );
}
I am very much used to this pattern, although I dislike it a lot. The main reason for not defining the class is usually that I the functor will be used within a STL and templates do not like structs defined inline of a function. However in my case the use_functor() function will be a normal method, so I can define the functor inside of the function itself (each functor is only used within one function).
void function() {
struct functor{
functor( type & member ) : m_member( member ) {}
void operator()( ... ) {...}
type & m_member;
};
use_functor( functor(...) );
}
This seems somewhat improved, but still requires a lot more ugly code that I would like. For example I would like to get rid of the name of the functor altogether. I know it is possible to create an anonymous struct, if I only ever use one value.
void function() {
struct{
// functor( type member ) : m_member( member ) {}
void operator()( ... ) {...}
// type & m_member;
} callback ;
use_functor( callback );
}
However at this point I have no clue on how to provide the necessary data members. Since the struct is anonymous it does not have a constructor. I could easily set the member, because it is public, but again this would add a line which I dislike.
The goal is to leave it in a state that as little as possible needs to be changed once we switch to a compiler that has clean lambdas which would allow to eliminate this problem altogether.
How would you go about doing this?
With regards to the initalisation of the member variables of an anonymous struct without a constructor you can do:
void function() {
type the_thing;
struct {
void operator()( ... ) {...}
type & m_member;
} callback = {the_thing};
use_functor( callback );
}
to set the type & reference m_member in callback.
You could try boost lambda library or boost::phoenix. They are both designed to do lambda style operations without actual lambda support. Since they are template based, errors can be difficult to debug when something doesn't work as expected.
Expanding on the answer by awoodland:
#define MY_LAMBDA(name, memberType, memberValue, body) \
struct { \
void operator()( ... ) body \
memberType & memberValue; \
} name = {memberValue}
void function() {
type thing_to_capture;
MY_LAMBDA(callback, type, thing_to_capture
{
std::cout << thing_to_capture << std::endl;
});
use_functor( callback );
}
You can use MY_LAMBDA anywhere you can define a struct. Unfortunately, without variadic macros, you have to wrap all captured objects into a single object, and you have to specify the type of that object in the "lambda declaration"
Also note that the equivalent using a lambda would be:
void function() {
type thing_to_capture;
auto callback = [&thing_to_capture]()
{
std::cout << thing_to_capture << std::endl;
};
use_functor( callback );
}