Using 'Std::Function<Void(...)>' to Call Non-Void Function

Using `std::function void(...) ` to call non-void function

Your code has undefined behavior. It may or may not work as you expect. The reason it has undefined behavior is because of 20.8.11.2.1 [func.wrap.func.con]/p7:

Requires: F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument types ArgTypes and return type R.

For f to be Callable for return type R, f must return something implicitly convertible to the return type of the std::function (void in your case). And int is not implicitly convertible to void.

I would expect your code to work on most implementations. However on at least one implementation (libc++), it fails to compile:

test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>'
std::function<void(int)> ff = f;
^ ~

Ironically the rationale for this behavior stems from another SO question.

The other question presented a problem with std::function usage. The solution to that problem involved having the implementation enforce the Requires: clause at compile time. In contrast, the solution to this question's problem is forbidding the implementation from enforcing the Requires: clause.

why can I call a non-void member function as a void one in c++?

You can discard the return value. It's no good style in general, but you can always do it.

That's one of the reasons why we can't overload on the return type. So if you'd define another function void test(), the call wouldn't be possible because of ambiguity.

If you want your compiler to warn such cases in which you (un)intentionally discard the return value, pass the flag -Wunused-result (for GCC). [I don't know the flags for other compilers]

In general, almost all return values make sense, so some people use this macro to detect cases where they unintentionally discarded the value, especially if the return value is something like an error code which should be checked afterwards.

If you want to enable the warning for a particular function, you can put an attribute at the end of the signature (also for GCC, for MSVC have a look at this question):

std::vector<int> __attribute__((warn_unused_result)) test() {
return std::vector<int>(1,0);
}

See also: How to raise warning if return value is disregarded?

Thus, if you call the function but don't use the return value, you get a warning. Note that warnings don't make compilation fail, for this you need to add -Werror to the compiler flags.

Casting lambda with non-void return type to function pointer

The problem is that you are using C-style explicit casts. These are notoriously dangerous.

Here in this case the problem is that fun3 (in contrast to fun2) already decays to a function pointer of type int(*)().

You then cast it to void(*)(). This works because the C-style cast will try to do different C++ cast expressions until one works. In particular it will also try a reinterpret_cast.

reinterpret_cast<voidFunctionType>(fun3)

works, because reinterpret_cast can cast any function pointer to any other function pointer.

However, you are not allowed to call the function through the obtained pointer. Doing so causes your program to have undefined behavior. As you can see this cast is of very limited use and dangerous if you are not aware of it.

Don't use C-style casts, use static_cast<voidFunctionType>(fun3) instead and you will get the appropriate compile-time error in both cases.

You cannot use a function (whether free function or lambda) that returns one type as if it returned another (or no) type. Casting the lambda that returns int to void(*)() therefore doesn't make sense.


If you really want to save arbitrary function pointers you can make the lambda cast work by first converting it to a function pointer and then casting it to the destination function pointer type with a reinterpret_cast. I would still not use C style casts, because the reinterpret_cast will at least make it clear what kind of cast you are intending to do:

auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);

The unary + is a common trick to force lambda to function pointer conversion. Note however also that only lambdas without capture can be converted to function pointers.

As I explained above though, you must cast the pointer back to its original type before calling it, so you need to store the type information somewhere. I am not sure how you intend to do that, but you probably need to implement some extended version of std::function, see e.g. this question for how std::function does it.

Passing a non-static method or std::function void(...) as a void (*) argument

As stated, this is not possible since there is no way to meaningfully construct a plain function pointer from a (non static) method, a closure, or a std::function object.

Roughly speaking, each of the constructs above are logically formed by two parts: some fixed code (a pointer to a fixed, statically known function), and variable data (the object at hand, or the captures for a closure). We can not simply throw away the second part.

That being said, I would recommend to check if the library will call the dispatcher passing a user-defined pointer for its void * argument. It's somewhat common to see C style library functions like

void register_callback(void (*dispatcher)(int,int,void *), void *user_data);

This is a trick to allow to simulate closures in C, passing the two "parts" of the closure separately.

If that's the case, instead of

// not working, just for example
std::function<void(int, int)> f;
register_callback(f);

You can write

// Make sure f will live long enough.
// I'm using new to stress the point, but you can use anything
// else provided that the pointer will be valid when f is
// called.
std::function<void(int, int)> *pf = new ...;
register_callback(call_the_function, pf);

provided you have defined

// fixed function, independent from the std::function object
void call_the_function(int x, int y, void *p) {
std::function<void(int,int)> *pf =
(std::function<void(int,int)>*) p;
(*pf)(x,y);
}

If you used new to keep the pointer valid long enough, remember to delete it when the callback is no longer needed.

Is there a way to pass a void function with any type and amount of arguments as an argument in a method and store it in a data member? (C++)

From what I understand, you want to call a function void(), where caller might register other function type with bind parameters. You might do it with std::function:

class ExampleClass {
public:
void saveFunction(std::function<void()> f) {
this->f = f;
}
void call() { f(); }
private:
std::function<void()> f;
};

with usage

void foo();
void bar(std::vector<std::any>);

std::vector<std::any> v;

ExampleClass ex;

ex.SaveFunction(&foo); ex.call(); // foo();
ex.SaveFunction([&]() { bar(v); }); ex.call(); // bar(v);
// You might capture by copy/move if you prefer (instead of by reference)

C++ How to make a non void function return nothing for if else statements?

One way to handle this would be a std::optional<std::string>

#include <optional>

std::optional<std::string> dingas(std::string something)
{
string letter;
cout << "press a";
cin >> letter;
if (letter==something){
return "a";
}
else
{
std::cout << "wrong letter";
return std::nullopt;
}
}

[1] https://en.cppreference.com/w/cpp/utility/optional

Isn't the template argument (the signature) of std::function part of its type?

The problem is that both function<int()> and function<int(int)> are constructible from the same function. This is what the constructor declaration of std::function looks like in VS2010:

template<class _Fx>
function(_Fx _Func, typename _Not_integral<!_Is_integral<_Fx>::value, int>::_Type = 0);

Ignoring the SFINAE part, it is constructible from pretty much anything.

std::/boost::function employ a technique called type erasure, to allow arbitary objects/functions to be passed in, so long they satisfy the signature when being called. One drawback from that is, that you get an error in the deepest part of the implementation (where the saved function is being called) when supplying an object which can't be called like the signature wants it to, instead of in the constructor.


The problem can be illustrated with this little class:

template<class Signature>
class myfunc{
public:
template<class Func>
myfunc(Func a_func){
// ...
}
};

Now, when the compiler searches for valid functions for the overload set, it tries to convert the arguments if no perfect fitting function exists. The conversion can happen through the constructor of the parameter of the function, or through a conversion operator of the argument given to the function. In our case, it's the former.

The compiler tries the first overload of a. To make it viable, it needs to make a conversion. To convert a int(*)() to a myfunc<int()>, it tries the constructor of myfunc. Being a template that takes anything, the conversion naturally succeeds.

Now it tries the same with the second overload. The constructor still being the same and still taking anything given to it, the conversion works too.

Being left with 2 functions in the overload set, the compiler is a sad panda and doesn't know what to do, so it simply says the call is ambigious.


So in the end, the Signature part of the template does belong to the type when making declarations/definitions, but doesn't when you want to construct an object.


Edit:

With all my attention on answering the title-question, I totally forgot about your second question. :(

Can I circumvent it or will I have to keep the (annoying) explicit casts?

Afaik, you have 3 options.

  • Keep the cast
  • Make a function object of the appropriate type and pass that

    function<int()> fx = x;
    function<int(int)> fy = y;
    a(fx);
    a(fy);

  • Hide the tedious casting in a function and use TMP to get the right signature

The TMP (template metaprogramming) version is quite verbose and with boilerplate code, but it hides the casting from the client. An example version can be found here, which relies on the get_signature metafunction that is partially specialized on function pointer types (and provides a nice example how pattern matching can work in C++):

template<class F>
struct get_signature;

template<class R>
struct get_signature<R(*)()>{
typedef R type();
};

template<class R, class A1>
struct get_signature<R(*)(A1)>{
typedef R type(A1);
};

Of course, this needs to be extended for the number of arguments you want to support, but that is done once and then buried in a "get_signature.h" header. :)

Another option I consider but immediatly discarded was SFINAE, which would introduce even more boilerplate code than the TMP version.

So, yeah, that are the options that I know of. Hope one of them works for you. :)

cannot convert ‘std::function void*() ’ to ‘void* (*)(void*)’

I suppose there are two kinds of answers I can give to this one: I can show you the proper way to do what you're trying to do (start a thread) in C++, or I can show you how to squeeze a std::function object into pthread_create. The first has more practical value, while the second serves to explain how pthread_create handles context. There's value in both, so:

1. How to call a std::function<void*()> object in a new thread

Since C++11, the standard library contains facilities for multithreading. In your case, we have a function with a return value, so the task is to

  1. Call the function asynchronously, and
  2. Get the return value when we need it.

The most straightforward way to do this is to use std::async and std::future<void*>. Consider this simple example to make one call asynchronously:

std::function<void*()> f; // the function to call

// Call f asynchronously. It is possible to omit the std::launch::async
// parameter, in which case it is up to the implementation when or even
// if a thread is spawned to make the call.
// The future object represents a handle to the void* value that f will
// eventually return (i.e., the future value).
std::future<void*> fut = std::async(std::launch::async, f);

// Do some other stuff while we're waiting

// get f's return value. This will wait if the thread is not yet finished.
void *value_returned_by_f = fut.get();

In your case, you want to call more than one function and get the return values at your leisure, so you want to store the std::future<void*> objects somewhere. As luck would have it, the structure of your code can be mostly preserved:

vector<function<void*()>> signals;
vector<std::future<void*>> signal_futures;

// Master Signal Handler
void MasterSignalHandler()
{
for (auto & signal_handler : signals)
{
signal_futures.push_back(std::async(std::launch::async, signal_handler));
}
}

You can then later retrieve the return values from signal_futures at your leisure.

Note that if the functions did not return values, you could use std::thread instead of std::future:

vector<function<void()>> signals;
vector<std::thread> signal_threads;

// Master Signal Handler
void MasterSignalHandler()
{
for (auto & signal_handler : signals)
{
signal_threads.emplace_back(signal_handler);
}
}

Instead of .get()ing the result from the future, you would then eventually .join() the threads. Using std::future<void> would also work, so this is mostly a matter of taste, really.

2. How to force std::function<void*()> into pthread_create

We've just discussed the sensible way to go about the problem, now let's take a look at the dirty bits. The reason your original code does not compile is that pthread_create expects a memory address pointing to a function (i.e., machine code) that it can execute, and that signal_handler is not such a memory address but a complex object with state. pthread_create cannot handle it.

However: if you look carefully, you will note that the function pthread_create expects takes a void* argument, and that pthread_create takes a void* argument later in its signature -- this latter argument is passed to the function when the thread is started. If we really wanted to, we could use this mechanism, and in fact on POSIX-based systems, std::thread will generally do exactly this for you. For example:

void *thread_stub(void *context) {
// context is static_cast<void*>(&f) below. We reverse the cast to
// void* and call the std::function object.
std::function<void*()> &func = *static_cast<std::function<void*()>*>(context);
return func();
}

// ...

std::function<void*()> f;

// IMPORTANT: Used this way, f must not go out of scope while the thread
// is running because the thread holds a pointer to it!
pthread_t thread_handle;
pthread_create(&thread_handle, NULL, thread_stub, &f);

Note that I do not recommend doing it this way. It is ugly, and it has the problem mentioned in the comment above. std::thread and its associated classes in the standard library solve all these issues for you, so there's no need to reinvent this particular wheel.



Related Topics



Leave a reply



Submit