I have a function that acts as a "function dispatch." This function contains a variable named next_func, which is initialized to the first function to load. Then, inside an infinite loop, the next_func is set to the return value of itself.
My question is, besides using auto, what type does next_func need to be? Here's some conceptual code (using auto) to give an idea of what I'm looking for:
void FunctionDispatch()
{
auto next_menu = first_menu;
while (next_menu != app_exit)
{
next_menu = next_menu();
}
}
auto first_menu()
{
auto return_menu = first_menu; // Set to itself for 'auto', but I don't want to have to do this
std::cout << "2 or 3? ";
unsigned input = 0;
std::cin >> input;
switch (input)
{
case 2:
return_menu = second_menu;
break;
case 3:
return_menu = third_menu;
break;
default:
break;
}
return return_menu;
}
I like using auto for trivial types, but I don't really like relying on it because I don't know how to address the type I'm wanting, which is why I'm wondering what auto actually is here and how to explicitly declare the variables and function return types (probably using type aliases since that's most sensible).
Something to note:
All functions that FunctionDispath() can call take no parameters and return function pointers to other functions that take in no parameters and return the same type of function pointers.
I'd prefer an answer that explains both what the full type would be with no type aliases and how to use a type alias here.
First off, cool! This reminds me of middleware frameworks, or coroutines with tasks and event loops.
Doing this with straight-up function pointers will result in an infinitely recursive type, as many have mentioned. But if each task is a callable object, then you don't need recursive types as a forward reference will do. You can inherit std::function to make it easy:
struct task : std::function<task()> {
using std::function<task()>::function;
};
Then you can assign functions to it. You can also bind arguments with std::bind, or even use the default constructor to make an empty function with no target:
task n_hellos(int count) {
if (count) {
std::cout << "hello\n";
return std::bind(n_hellos, count-1);
}
return task();
}
You can cast an std::function to bool to see if it is empty, allowing for a terminal case. The event loop below quits when the next task is empty:
int main() {
task current_task = std::bind(n_hellos, 5);
while (current_task) {
current_task = current_task();
}
} // prints "hello" five times
Demo: https://godbolt.org/z/dHaSWC
Related
I want to make Dialog handler for my app that will contain pointer to method that will be invoked when user answer "yes" and pointer to method for "no" and the main problem that these methods can have various args or without it so i dont know how to declare this variable.
class Dialog
{
protected:
Dialog()
{
}
static Dialog* singleton;
public:
Dialog(Dialog &other) = delete;
void operator=(const Dialog &) = delete;
static Dialog *instance();
string question;
?? method_yes;
?? method_no;
static bool has_dialog();
static void clear();
};
Dialog* Dialog::singleton = nullptr;
Dialog* Dialog::instance()
{
if (singleton == nullptr) {
singleton = new Dialog();
}
return singleton;
}
bool Dialog::has_dialog()
{
return singleton != nullptr;
}
void Dialog::clear()
{
if (singleton)
{
delete singleton;
singleton = nullptr;
}
}
So there is my class for dialog with user, when i want to ask user something i do
auto yes = []()
{
ExitProcess(0);
};
Dialog::instance()->question = "Do you want to exit?";
Dialog::instance()->method_yes = yes;
And somewhere upper or whatever i have answer handling
if (Dialog::has_dialog())
// render question and buttons
// if pressed button yes
Dialog::instance()->method_yes();
Dialog::clear();
And what if for example i want to manage exit code so my lambda will be
auto yes = [](int code)
{
ExitProcess(code);
};
But then there is a new argument so i cant just use
void(*method_yes)();
for declaration
At the end of the day, C++ is a strongly typed language and you'll have to provide the set of expected possible arguments in your function signature.
Since you don't want that, there are some techniques to circumvent it so let's name a few:
The old (old old) void* trick from C. You declare your function pointer as
void (*fptr)(void* state);
and then you're free to interpret state however you wish in your fptr, e.g. if state==nullptr you can assume there are "no arguments". Note that this approach is not type safe and can cause a lot of headaches if users don't respect the agreed upon protocol.
You bundle all your state in your callable and your function pointer becomes something like std::function<void()>. This way you can write:
std::function<void()> fptr = [code]() { /* ... */ };
This is the nerfed version of the above, meaning your lambdas are now responsible for capturing the state you'd be passing to the function as arguments.
A pattern I'm using lately involves C++20 designated initializers like so:
struct Argument
{
std::optional<int> code;
std::optional<std::string> name;
std::optional<float> value;
};
void (*fptr)(Argument arg); // Argument is elastic, i.e.
// it can be formed as:
// {} -> no arguments
// {.code=1} -> 1 argument
// {.code=1, value=2.}-> 2 arguments
// etc
// Fields not mentioned default to
// nullopt, which means you have
// an easy way of telling them apart
int main ()
{
fptr = [](Argument arg) {
std::cout << arg.code.value_or(0) << std::endl;
std::cout << arg.name.value_or("no name") << std::endl;
std::cout << arg.value.value_or(42) << std::endl;
};
fptr({});
std::cout << "-------------\n";
fptr({.name="Garfield"});
std::cout << "-------------\n";
fptr({.code=3, .value=3.14});
std::cout << "-------------\n";
}
This is a type-safe alternative to (1). You declare the expected set of arguments in Argument but since they are optional you can call fptr({}) and mark everything as "non existent" (the no args case) or even initialize one or more arguments explicitly e.g. fptr({.code=3, .value=3.14}). Inside fptr you can inspect whether an optional variable is "filled" and this gives you the freedom to act accordingly (demo).
If all this still seems unattractive, I wrote a post some years ago on how to create overload sets out of lambdas. Essentially the technique allows you to write things like:
auto fptr = overload(
[]{ /*...*/ }, // A
[](int code) { /*...*/ }); // B
fptr(); // Calls A
fptr(22); // Calls B
Again this means that all possible solutions (sets of functions of different types) are known at compile time, but you dodge the pain of creating that set explicitly.
Finally I'd re-visit the design before resorting to such solutions, maybe a simpler path exists e.g. express the exit functions as a hierarchy and have a factory method to generate the active function at runtime or even reconsider why should an exit function be tweakable at runtime.
I was wondering if there's an elegant solution for the following issue:
Let's say I'd like to have a variable holding a value with a pretty complex type and would the compiler to automatically infer it's type, but declare first and give value later in the code because of initialization in an if statement.
For example:
{
auto a;
if (some predicate)
a = init_a(1);
else
a = init_a(2);
}
Obviously this code doesn't compile, but the I think that the compiler has all the information it needs to infer the type.
If 'a' was just an int, this was not a problem, but if the type is a complex template, I don't want to have to write it (or in some cases even know it).
Also, i wouldn't want to call the default constructor of a and then write over it.
Possible solutions:
Template the type of 'a'.
initialize 'a' using a lambda and move the predicate into the lambda.
Just write the type of 'a' instead auto.
Use a void pointer/shared_ptr and then init 'a' on the heap.
Each of these has its own drawbacks.
Is there a more elegant solution for it?
The compiler doesn't have infinite lookahead what is happening further on in the code. It only knows what's happening at the current statement. Therefore it can't deduce any types without an initializer.
If you don't know the return-type of init_a then you could use decltype:
decltype(init_a(1)) a;
You can also use a lambda call to initialize the variable:
auto a = [ /* Captures needed for the condition... */ ]()
{
if (some_condition)
return init_a(1);
else
return init_a(2);
}(); // Call the lambda immediately
Or, as mentioned in many comments, use the ternary conditional expression:
auto a = some_condition ? init_a(1) : init_a(2);
There's a technique called "Immediately Invoked Lambda Expression" that is using lambda to initialize a variable in a complex way. Using this approach your a can be const which improves const-correctness. More details here.
For a simple binary predicate, consider just using the ternary operator:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = somePredicate(input) ? initA(1) : initA(2);
}
for more complex initialization logic (beyond a binary case), wrap the initialization logic in a lambda:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = []() {
if (somePredicate(input)) { return initA(1); }
else if (input == 100) { return initA(100); }
else { return initA(2); }}();
}
Both these approaches come with additional possibility of making the variable to be initialized const.
If the return types of your lambda are different but convertible to some type then you can force the return type (note the -> is mandatory when specifying a return type):
auto a = [=]() -> ConvertedType {
if (some_predicate) {
return CovertibleType1(1);
} else if (other_predicate) {
return ConvertibleType2(2);
}
return ConvertibleType3(3);
}();
Though I realize this basically defeats the auto declaration...
I want to create a thread of the function ahrs thats in my AHRS class. This function is in an infinite loop and calcs something the whole time and puts those calculations in variables. I want to pass those variables to my PID
int main() {
AHRS* a = new AHRS();
std::thread ahrs(a->ahrs());
PID* p = new PID();
float pitch;
while(1) {
pitch = a->getPitch();
std::cout << "pitch: " << pitch << " pid: " << p->getError(0, pitch, 1) << std::endl;
usleep(100000);
}
}
but i get the error
main_ahrs.cpp: In function ‘int main()’:
main_ahrs.cpp:26:28: error: invalid use of void expression
my ahrs.cpp looks like this:
#include "AHRS.h"
AHRS::AHRS() {
//something
}
AHRS::~AHRS() {}
void AHRS::ahrs() {
//something
while(1) {
//something
}
}
float AHRS::getPitch() {
//return something
}
float AHRS::getRoll() {
//return something
}
float AHRS::getYaw() {
//return something
}
thanks for your help
a->ahrs()
That is not how you name a function. That is how you call an expression and use its result for something. The result of the function is of void type (that is, there isn't one) so using this function call as an expression (and certainly for a function reference/object/handle/wrapper/pointer!) is just not going to work.
The function is called AHRS::ahrs.
A further complication is that it is a member function, so you have to bind the implicit this parameter, like so:
std::thread ahrs(std::bind(&AHRS::ahrs, a));
The binding creates a sort of pseudo-function reference that already has the first argument sorted out for you, so that you (or, in this case, the thread code, which has no ability or desire to guess what the object instance should be) does not need to.
Conveniently, thread can do the binding for you, though, so:
std::thread ahrs(&AHRS::ahrs, a);
should suffice.
Try like this:
#include <functional>
and then:
std::thread ahrs(std::bind(&AHRS::ahrs, a));
The way you are doing, you are calling the a->ahrs() method, that returns void. You must pass in to std::thread something that can be called: a function pointer, or something like that, not void.
In this case of my suggestion, you will pass to std::thread the return from std::bind, that is a callable object built with a pointer to the method and a pointer to the AHRS object.
Lambda is your friend.
int main() {
AHRS* a = new AHRS();
std::thread ahrs(a->ahrs());
what the above does is it calls a->ahrs() (in main), takes its return value and passes it to the thread constructor. This isn't what you want.
Instead:
AHRS* a = new AHRS();
std::thread ahrs([a]{a->ahrs();});
will create a closure (or lambda) that consists of "do a call of a->ahrs()".
It then passes that closure to std::thread, which runs it on a different thread.
The [a] says "this is a closure, and it captures a (copy of) a". Then the body {a->ahrs();} says what the closure does.
In general, passing lambdas to std::thread is easier to reason about than passing the alternatives. There is a modest problem in that move-parameters require C++14 to work.
Using std::bind or the variardic constructor of std::thread are alternatives. I prefer passing code to passing data in this case, and passing a lambda closure is basically passing code.
So I am unsure why this wont work, ive tried some googling, i just cant find out what the problem is
void Player::Cmd(std::vector<std::string> &tokens)
{
std::string str = tokens[0];
std::map<std::string, void (Player::*)()>::iterator it = playerCommands.find(str);
Func fun;
if (it != playerCommands.end())
{
fun = it->second; //i tried it->second(); same issue
fun(); //error C2064: term does not evaluate to a
//function taking 0 arguments
}
else
{
std::cout << "What? \n";
}
}
git hub for the project
https://github.com/lordkuragari/TextRPG
Contrary to your belief, your map doesn't hold function pointers. So you cannot call the elements in the map.
Rather, your map contains pointers to member functions. Non-static member functions aren't functions and cannot be called; rather, they have to be invoked on an object. You can invoke a member function on an object given by a pointer p via a function pointer ptfm like this:
(p->*ptmf)();
In your case, presumably you want to use p = this and ptfm = fun, so it'd be:
(this->*fun)();
Or, without the local variable:
(this->*it->second)();
In C++17 you can also use std::invoke(it->second, this).
I'm working on a Visual C++ 2010 Express console application.
Before I go into detail, the summary here is: How can I make an array/list/vector of functions and call them from that array?
So I'm having a little difficulty with function pointers. I'm writing a 'Terminal' class, which in turn has a member class 'CommandMap'. The purpose of the CommandMap class is to store a vector/array of functions and the strings that represent them in another vector/array. I want the functions to be called (only) when the class calls them from the vector, but it executed only when I added it to the vector and not when trying to call it.
I tried defining a type for it:
typedef void (*CmdCallback)();
I declared a vector to contain them:
vector<string> CmdNames;
vector<CmdCallback> CmdFuncs;
I add them like so:
// Map a new command
bool CommandMap::Map(string name, CmdCallback func)
{
if (!IsNullOrSpace(name) && func != NULL)
{
if (!Exists(name))
{
CmdNames.push_back(name);
CmdFuncs.push_back(func);
return true;
}
}
return false;
}
And I try calling them like this:
// Get a command callback from its identifier
CmdCallback CommandMap::GetFunc(string name)
{
int index = IndexOf(name);
if (index == -1) return NULL;
else return CmdFuncs.at(index);
}
// If the given string is a command indentifier
// it will invoke the associated callback.
bool CommandMap::Exec(string input)
{
for each (string id in CmdStrings)
{
if (input == id)
{
CmdCallback cmd;
cmd = GetFunc(id);
cmd();
return true;
}
}
return false;
}
I tried using this:
CmdCallback SayHello()
{
cout << "Hello World!" << endl;
return NULL; // Forces me to return null, guessing since it's
// not 'void' but a 'void' pointer it must return something
}
int main(int argc, char *argv[])
{
App = new Terminal(argc, argv);
App->Commands->Map("say", SayHello);
while (!App->ExecComplete)
{
App->WaitEnter();
App->Commands->Exec("say");
App->WaitEnter();
App->ExecComplete = true;
}
return App->ExitCode;
}
This works, at first. The function gets called when I try to Map() it though. And when I Exec() "say", it finds the callback, but when it tries to call it, I get this runtime error, to which I can see no detail other than the option to break or continue. The code it gives me is.
I pretty much want to abandon my method and try a new approach, maybe I'm going the wrong way with the void pointer typedef, and I need to throw a '&' or a '*' somewhere I haven't like in the Map() argument list. Maybe a vector isn't the best way to do this either.
Basically, I am asking how I can I make an array of functions that can (and only) be called by referencing them from the array. I'm terrible with callbacks.
You can use std::functions, or, if you don't have C++11 support, boost::function. These are function object wrappers that can be easily constructed from free or member functions. You can store these in a standard library container or simple array.
If I understand correctly you actually want to declare SayHello as void SayHello() so that a pointer to SayHello has the type void (*)() (i.e. CmdCallback) which is what you need for your vector of functions.