The idea is to call different functions based on their index in table.
But line 27 generates the runtime error ((
I tried to fix but didn't succeed (((
Here's the simplified code:
#include <iostream>
void f1 (void) {
std::cout << "f1" << "\n";
}
void f2 (void) {
std::cout << "f2" << "\n";
}
typedef void (*fPtr[3])(void); // simple "[]" instead of "[3]" gets the compile error
class modeChanger {
public:
modeChanger (fPtr funcArray);
void op ();
private:
fPtr *_funcArray;
};
modeChanger::modeChanger (fPtr funcArray) {
_funcArray = (fPtr *) funcArray;
}
void modeChanger::op () {
(*_funcArray[0])();
(*_funcArray[1])(); // Line 27: this line generates a runtime error! Just comment it to get all work
}
void (*modeFuncArray[])(void) = {f1, f2, f2};
modeChanger *mode = new modeChanger (modeFuncArray);
int main() {
(*modeFuncArray[1])(); // Works fine
mode->op(); // generates a runtime error
return 0;
}
This works good:
(*_funcArray[0])();
as well as this:
(*modeFuncArray[1])();
but this generates a runtime error...
(*_funcArray[1])();
Seems that incrementing of _funcArray is incorrect for some reason.
fPtr *_funcArray; this is the pointer to array, not an array of pointers. You suppressed warnings with help of type casts. See bellow the fixed code.
#include <iostream>
void f1 (void) {
std::cout << "f1" << "\n";
}
void f2 (void) {
std::cout << "f2" << "\n";
}
typedef void (*fPtr)(void);
class modeChanger {
public:
modeChanger (fPtr *funcArray);
void op ();
private:
fPtr *_funcArray;
};
modeChanger::modeChanger (fPtr *funcArray) {
_funcArray = funcArray;
}
void modeChanger::op () {
(*_funcArray[0])();
(*_funcArray[1])(); // Line 27: this line generates a runtime error! Just comment it to get all work
}
void (*modeFuncArray[])(void) = {f1, f2, f2};
modeChanger *mode = new modeChanger (modeFuncArray);
int main() {
(*modeFuncArray[1])(); // Works fine
mode->op(); // generates a runtime error
return 0;
}
Applying #Someprogrammerdude's advice:
#include <iostream>
#include <array>
#include <functional>
void f1 (void) {
std::cout << "f1" << "\n";
}
void f2 (void) {
std::cout << "f2" << "\n";
}
using fPtr = std::function<void()>;
using fPtrs = std::array<fPtr, 3>;
class modeChanger {
public:
modeChanger (fPtrs funcArray);
void op ();
private:
fPtrs _funcArray;
};
modeChanger::modeChanger (fPtrs funcArray) : _funcArray(funcArray) { }
void modeChanger::op () {
_funcArray[0]();
_funcArray[1]();
}
int main() {
fPtrs modeFuncArray = {f1, f2, f2};
modeChanger mode(modeFuncArray);
modeFuncArray[1]();
mode.op();
return 0;
}
And thus instead of "hard to declare" C types, we have things as easy as int, and all is well.
as you use c++, you should use c++ features and not C, you should use <functional>
#include <iostream>
#include <functional>
void f1(void) {
std::cout << "f1" << "\n";
}
void f2(void) {
std::cout << "f2" << "\n";
}
typedef void(*fPtr[3])(void); // simple "[]" gets the compile error
class modeChanger {
public:
modeChanger(std::function<void(void)>* funcArray);
void op();
private:
std::function<void(void)> * _funcArray;
};
modeChanger::modeChanger(std::function<void(void)>* funcArray) {
_funcArray = funcArray;
}
void modeChanger::op() {
_funcArray[0]();
_funcArray[1](); // this line generates a runtime error! Just comment it to get all work
}
std::function<void(void)> modeFuncArray[] = { f1, f2, f2 };
modeChanger *mode = new modeChanger(modeFuncArray);
int main() {
modeFuncArray[1](); // Works fine
mode->op(); // generates a runtime error
return 0;
}
Related
I want function f2 in structure node to call function f1 in node instead of global function f1.
#include <iostream>
#include <functional>
int f1()
{
return 1;
}
int f2()
{
return f1();
}
struct node
{
int f1()
{
return 2;
}
std::function<int()> f2 = ::f2;
};
int main()
{
node a;
std::cout << a.f2() << "\n";
return 0;
}
I want function f2 in structure node to call function f1 in node instead of global function f1.
You can achieve this by adding a (second) constructor to node which accepts a callable to assign to node::f2. Something like this, passing in a lambda to that constructor to capture the object itself:
#include <iostream>
#include <functional>
int f1()
{
return 1;
}
int f2()
{
return f1();
}
struct node
{
node () = default;
node (std::function<int()> assign_to_f2) { f2 = assign_to_f2; }
int f1 ()
{
return 2;
}
std::function<int()> f2 = ::f2;
};
int main()
{
node a;
std::cout << a.f2() << "\n";
node b ([&b] () { return b.f1 (); });
std::cout << b.f2() << "\n";
return 0;
}
Output:
1
2
Live Demo
here is my code, when i try running this, main does output the information placed into the LoggerComponent, but not the Logger itself. I don't know why, what could be preventing the logger from passing information into the underlying loggercomponent?
i tried using information from http://www.cplusplus.com/reference/map/map/
and from https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/
logger.cpp:
#include "logger.hpp"
Logger::Logger(bool verbose, bool fileoutput)
{
if(verbose)
{
LoggerComponent c1(LoggerLevel::DEBUG, &std::cout);
addLogger (LoggerType::CONSOLE, &c1);
c1.output (LoggerLevel::DEBUG, "This is the start of console output");
}
if(fileoutput)
{
}
}
void Logger::output(LoggerLevel level, std::string message)
{
for(auto& x : components)
{
x.second->output (level, message);
}
}
void Logger::addLogger(LoggerType type, LoggerComponent* component)
{
if(components.find (type) == components.end ())
components.emplace(type, component);
}
LoggerComponent* Logger::getLogger (LoggerType type)
{
if(components.find (type) != components.end ())
return components.at (type);
return nullptr;
}
void Logger::clearLoggers()
{
components.clear ();
}
void Logger::removeLogger(LoggerType type)
{
if(components.find (type) != components.end ())
components.erase (type);
}
logger.hpp
#ifndef LOGGER_HPP
#define LOGGER_HPP
#include "loggercomponent.hpp"
#include <map>
enum class LoggerType
{
CONSOLE,
FILE
};
class Logger
{
public:
explicit Logger(bool verbose, bool fileoutput);
void output(LoggerLevel level, std::string message);
void addLogger(LoggerType type, LoggerComponent* component);
void removeLogger(LoggerType type);
void clearLoggers();
LoggerComponent* getLogger(LoggerType type);
private:
std::map<LoggerType, LoggerComponent*> components;
};
#endif // LOGGER_HPP
main.cpp
#include "logger.hpp"
int main()
{
int* p;
int i = 5;
int j = 5;
p = &i;
std::cout << p << std::endl;
p = &j;
std::cout << p << std::endl;
LoggerComponent c(LoggerLevel::DEBUG, &std::cout);
c.output (LoggerLevel::INFO, "Hello World!");
c.output (LoggerLevel::CRITICAL, "Hello World!");
Logger c2(true, true);
std::cout << c.getOutputStream () << std::endl;
std::cout << c2.getLogger (LoggerType::CONSOLE)->getOutputStream () << std::endl;
c2.output (LoggerLevel::INFO, "Hello World!");
c2.output (LoggerLevel::CRITICAL, "Hello World!");
}
loggercomponent.hpp
#ifndef LOGGERCOMPONENT_HPP
#define LOGGERCOMPONENT_HPP
#include <iostream>
#include <string>
#include <ctime>
enum class LoggerLevel
{
INFO,
DEBUG,
WARNING,
ERROR,
CRITICAL
};
class LoggerComponent
{
public:
explicit LoggerComponent(LoggerLevel level, std::ostream* output);
LoggerLevel getMinimumLevel();
std::ostream* getOutputStream();
void setMinimumLevel(LoggerLevel level);
void setOutputStream(std::ostream* output);
void output(LoggerLevel level, std::string outputMessage);
private:
std::string getLevelString(LoggerLevel level);
LoggerLevel minimumLevel;
std::ostream* outputStream;
};
#endif // LOGGERCOMPONENT_HPP
loggercomponent.cpp
#include "loggercomponent.hpp"
LoggerComponent::LoggerComponent(LoggerLevel level,
std::ostream* output)
{
setMinimumLevel (level);
setOutputStream (output);
}
void LoggerComponent::setMinimumLevel(LoggerLevel level)
{
if(minimumLevel != level)
minimumLevel = level;
}
void LoggerComponent::setOutputStream(std::ostream *output)
{
if(outputStream != output)
outputStream = output;
}
LoggerLevel LoggerComponent::getMinimumLevel()
{
return minimumLevel;
}
std::ostream* LoggerComponent::getOutputStream()
{
return outputStream;
}
std::string LoggerComponent::getLevelString(LoggerLevel level)
{
switch (level) {
case LoggerLevel::INFO:
return "INFO";
case LoggerLevel::DEBUG:
return "DEBUG";
case LoggerLevel::WARNING:
return "WARNING";
case LoggerLevel::ERROR:
return "ERROR";
case LoggerLevel::CRITICAL:
return "CRITICAL";
}
return nullptr;
}
void LoggerComponent::output(LoggerLevel level, std::string outputMessage)
{
if(level >= minimumLevel)
{
time_t now = time(nullptr);
*outputStream << ctime(&now)
<< (getLevelString (level) + " >> " + outputMessage)
<< std::endl << std::endl;
}
}
output:
0x60fda8
0x60fdac
Tue Oct 01 12:29:14 2019
CRITICAL >> Hello World!
Tue Oct 01 12:29:14 2019
DEBUG >> This is the start of console output
0x6fd0cd00
0x60fdb0
You are storing a pointer to an object local to the constructor (c1) in components. It will be destroyed and the pointer invalid when you try to use it later.
Store the object itself (or a std::unique_ptr to it if you have a good reason not to store the object itself) in the map instead.
I want to be able to return a function from a class, so that I do not need to if-else through a return type.
I have a class that returns multiple strings. Instead, I want to return multiple functions.
#include <iostream>
class Handler
{
private:
public:
int handleMessage(int code)
{
return code+1;
}
};
void func1();
void func2();
void func3();
int main (int argc, char *argv[])
{
Handler handle;
int code = handle.handleMessage(0);
if(code == 1)
{
func1();
}
return 0;
}
void func1(){ std::cout << "1" << std::endl;}
void func2(){ std::cout << "2" << std::endl;}
void func3(){ std::cout << "3" << std::endl;}
What I want is: That the function handleMessage in the class Handler returns something so that in my main application I do not have to use if-else.
So the main looks like this:
function = handle.handleMessage(0);
And the application will choose which function it will run.
for example:
function = handle.handleMessage(0); //will run func1
function = handle.handleMessage(1); //will run func2
You can modify the member function such that it returns a function pointer, e.g.
using fptr = void (*)();
struct Handler
{
fptr handleMessage (int code)
{
if (code == 0)
return &func1;
else if (code == 1)
return &func2;
else
return &func3;
}
};
This can be invoked as follows
Handler handle;
auto f = handle.handleMessage(0);
f();
Note that the above if-else if-else dispatch isn't ideal. Prefer a data member that stores the function pointers and associates them with a code, e.g. using a std::unordered_map.
Note that when you need to return stateful function objects in the future, this approach will fail. Then, you need to embrace std::function which is able to wrap lambdas with closures or custom types with an operator() overload.
There are several ways to do so, the simplest one, you can use an std::function. In this example we returning a lambda function for each case. You can replace it with the functions you just wrote.
class Handler {
public:
std::function<void()> handleMessage(int code) {
code = code + 1; // ++code or whatever
if (code == X) {
return []() { std::cout << "Cool! I'am x!" << std::endl; };
} else if (code == Y) {
return []() { std::cout << "Cool! I'am x!" << std::endl; };
} else if (...) {
...
} else {
....
}
}
};
Then your main function becomes:
int main (int argc, char *argv[]) {
Handler handle;
const auto func = handle.handleMessage(0);
func();
return 0;
}
You can replace the swith/if case statement by an array storing the different functions, like they mentioned in the comments.
If you dont want to pay the extra virtual function call regarding the usage of an std::function, you can use an alias like the answer below or just the auto keyword:
class Handler {
public:
constexpr auto handleMessage(int code) {
code = code + 1; // ++code or whatever
if (code == X) {
return &func1;
} else if (code == Y) {
return &func2;
} else if (...) {
...
} else {
....
}
}
};
std::function is a powerful tool. The tiny brother is a simple function pointer.
I transformed MCVE respectively to return a function pointer:
#include <iostream>
typedef void (*FuncPtr)();
void func1();
void func2();
void func3();
void funcError();
class Handler
{
private:
public:
FuncPtr handleMessage(int code)
{
switch (code + 1) {
case 1: return &func1;
case 2: return &func2;
case 3: return &func3;
default: return &funcError;
}
}
};
int main (int argc, char *argv[])
{
Handler handle;
FuncPtr pFunc = handle.handleMessage(0);
pFunc();
return 0;
}
void func1(){ std::cout << "1" << std::endl;}
void func2(){ std::cout << "2" << std::endl;}
void func3(){ std::cout << "3" << std::endl;}
void funcError(){ std::cout << "ERROR!" << std::endl;}
Output:
1
Live Demo on coliru
You can return a function with return_type(*function_name)(argument_type1, argument_type2...) so a function that looks like:
double f(int a, int b);
has the name double(*f)(int, int).
Worth mentioning is C++11's std::function which requires the <functional> header. It has a more intuitive usage: std::function<double(int, int)> but also adds a bit of overhead.
I would also like to suggest the usage of C++17's std::optional as for the case when the variable code goes out of bounds. This implementation requires the <optional> header.
std::optional<void(*)()> handleMessage(int code){
switch (code) {
case 0: return std::optional(func1);
case 1: return std::optional(func2);
case 2: return std::optional(func3);
}
return std::nullopt; //empty
}
usage in main looks like the following:
Handler handle;
auto func = handle.handleMessage(0);
if (func.has_value()) {
func.value()();
}
as this allows to check if func.has_value() which is quite convenient.
Use an array of functions.
void func1(){ std::cout << "1" << std::endl; }
void func2(){ std::cout << "2" << std::endl; }
void func3(){ std::cout << "3" << std::endl; }
typedef void (* func ) () ;
class Handler {
public:
func handleMessage(int code)const{
static const func F[] = { func1, func2, func3 };
return F[ code ];
}
};
int main()
{
Handler handler;
func f = handler.handleMessage(0); // returns func1
f();
}
live example
you can map the ints to a function or lambda, but read befor what at() does and what happens if the key is not found!!
void function1()
{
std::cout << "q1" << std::endl;
}
void function2()
{
std::cout << "q2" << std::endl;
}
int main(int argc, char* argv[])
{
std::map<int, std::function<void(void)>> map;
map.insert(std::make_pair(1, function1));
map.insert(std::make_pair(1, function2));
map.at(1)();
I would like to offer solution without any if-else block. You just need to templatize your Handler::handleMessage function. Something like this:
// Class declaration
class Handler
{
private:
public:
template<int code>
void handleMessage();
};
and specialize the function template for particular codes:
// Function template specializations.
template<>
void Handler::handleMessage<1>()
{
std::cout << "1" << std::endl;
}
template<>
void Handler::handleMessage<2>()
{
std::cout << "2" << std::endl;;
}
template<>
void Handler::handleMessage<3>()
{
std::cout << "3" << std::endl;;
}
// All cases, except 1, 2 and 3
template<int code>
void Handler::handleMessage()
{
std::cout << "Anything else" << std::endl;;
}
The usage may look like:
Handler h;
h.handleMessage<1>(); // Prints 1
h.handleMessage<2>(); // Prints 2
h.handleMessage<3>(); // Prints 3
h.handleMessage<323>(); // Prints 'Anything else'
Why does this simple example not compile, and how can I get around the problem?
#include <iostream>
#include <boost/signals2/signal.hpp>
struct HelloWorld {
HelloWorld() {
i = 0;
}
void operator()() {
std::cout << "I is: " << i++ << std::endl;
}
void setup () {
sig.connect(this);
}
void run () {
sig();
}
boost::signals2::signal<void ()> sig;
private:
int i;
};
int main()
{
HelloWorld hello;
hello.setup();
hello.run();
hello.run();
hello.run();
return 0;
};
You are trying to connect to a pointer, which isn't possible. Instead you need to connect to a reference to your object:
void setup () {
sig.connect(boost::ref(*this));
}
class Foo {
public:
Foo() { do_something = &Foo::func_x; }
int (Foo::*do_something)(int); // function pointer to class member function
void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }
private:
int func_x(int m) { return m *= 5; }
int func_y(int n) { return n *= 6; }
};
int
main()
{
Foo f;
f.setFunc(false);
return (f.*do_something)(5); // <- Not ok. Compile error.
}
How can I get this to work?
class A{
public:
typedef int (A::*method)();
method p;
A(){
p = &A::foo;
(this->*p)(); // <- trick 1, inner call
}
int foo(){
printf("foo\n");
return 0;
}
};
void main()
{
A a;
(a.*a.p)(); // <- trick 2, outer call
}
The line you want is
return (f.*f.do_something)(5);
(That compiles -- I've tried it)
"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.
class A {
int var;
int var2;
public:
void setVar(int v);
int getVar();
void setVar2(int v);
int getVar2();
typedef int (A::*_fVar)();
_fVar fvar;
void setFvar(_fVar afvar) { fvar = afvar; }
void insideCall() { (this->*fvar)(); }
};
void A::setVar(int v)
{
var = v;
}
int A::getVar()
{
std::cout << "A::getVar() is called. var = " << var << std::endl;
return var;
}
void A::setVar2(int v2)
{
var2 = v2;
}
int A::getVar2()
{
std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
return var2;
}
int main()
{
A a;
a.setVar(3);
a.setVar2(5);
// a.fvar = &A::getVar;
a.setFvar(&A::getVar);
(a.*a.fvar)();
a.setFvar(&A::getVar2);
(a.*a.fvar)();
a.setFvar(&A::getVar);
a.insideCall();
a.setFvar(&A::getVar2);
a.insideCall();
return 0;
}
I extended Nick Dandoulakis's answer. Thank you.
I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.
Try (f.*do_something)(5);
#include<iostream>
using namespace std;
class A {
public:
void hello()
{
cout << "hello" << endl;
};
int x = 0;
};
void main(void)
{
//pointer
A * a = new A;
void(A::*pfun)() = &A::hello;
int A::*v1 = &A::x;
(a->*pfun)();
a->*v1 = 100;
cout << a->*v1 << endl << endl;
//-----------------------------
A b;
void(A::*fun)() = &A::hello;
int A::*v2 = &A::x;
(b.*fun)();
b.*v2 = 200;
cout << b.*v2 << endl;
}
I think calling a non static member of the class could also be done using a static member function.