Intro:
I'm coding in VS2010 basic calculator based on FSM patter. So, I need action map.
How correctly initialize a static two dimensional array of pointers to functions in C++?
I've already tried
static void (*action_map[])() = {A, pA}; //one dimension for example
or
static void (*action_map[])() = {&A, &pA};
and many others doesn't work.
ADDED
Everything should be done inside class.
Example below doesn't work for me
public class A {
public:
void func1() { cout << "func1\n"; }
void func2() { cout << "func2\n"; }
void func3() { cout << "func3\n"; }
void func4() { cout << "func4\n"; }
typedef void (*function_t)();
function_t function_array[2][2];
A();
};
A::A()
{
function_array[2][2] = { { func1, func2}, { func3, func4 } };
};
int main(array<System::String ^> ^args)
{
A * tst = new A();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
tst->function_array[i][j]();
}
}
return 0;
}
Please point what exactly I did wrong.
If your compiler supports C++11 initialiser lists, then you just need do drop the spurious array sizes in your assignment.
A::A()
{
function_array = { { func1, func2}, { func3, func4 } };
}
Or better still, initialise it directly, rather than assigning after default-initialisation:
A::A() : function_array { { func1, func2}, { func3, func4 } }
{}
If your compiler doesn't support C++11, you'll need to assign them by hand:
A::A()
{
function_array[0][0] = func1;
function_array[0][1] = func2;
function_array[1][0] = func3;
function_array[1][1] = func4;
}
You'll also need to make the functions static in order to store simple function pointers to them; if they have to be non-static members, then you'll need to either store member-function pointers and call them with a class instance, or store std::function objects, created using std::bind (or their Boost equivalents if you don't have C++11).
Note the type 'function_t' has changed:
class A
{
public:
void func1() { cout << "func1()\n"; }
void func2() { cout << "func2()\n"; }
void func3() { cout << "func3()\n"; }
void func4() { cout << "func4()\n"; }
typedef void (A::*function_t)();
static const function_t function_array[2][2];
};
const A::function_t A::function_array[2][2] = { { &A::func1, &A::func2 },
{ &A::func3, &A::func4 }
};
// Example use.
A my_a;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
std::mem_fn(A::function_array[i][j])(my_a);
}
}
If the array 'function_array' is changeable between class instances then a 'static const' is not appropriate and it must be populated in the constructor.
Both of them are fine if A and pA are the name of functions taking no arguments and returning a void type.
Since you're using MSVS2010 which has implemented many C++11 features, how about doing this:
void f1() {}
void f2() {}
void f3() {}
void f4() {}
std::vector<std::function<void()>> action_map = {f1, f2, f3, f4};
for(size_t i = 0 ; i < action_map.size(); ++i)
{
action_map[i](); //invoke action!
}
Related
I have a third party class Calculation with a function setCallback:
typedef void (*callback_function)(void);
class Calculation
{
public:
void setCallback(callback_function pFunc);
};
and my function I want to use as callback
void callback(int id);
I want to create, say, four (number known at compile time) objects of Calculation and set the callback for each object. I could do something like
void callback0() { callback(0); }
void callback1() { callback(1); }
void callback2() { callback(2); }
void callback3() { callback(3); }
int main() {
std::vector<Calculation> vec;
for (int i = 0; i < 4; i++) {
Calculation c = Calculation();
vec.push_back(c);
}
vec[0].setCallback(callback0);
vec[1].setCallback(callback1);
vec[2].setCallback(callback2);
vec[3].setCallback(callback3);
return 0;
}
Question: How can I achieve this without duplicating and repeating code?
I was thinking of lamdas, like
for (int i = 0; i < 4; i++) {
Calculation c = Calculation();
c.setCallback([i]() -> void {callback(i);});
vec.push_back(c);
}
but a lambda can only be converted to a function pointer if it does not capture.
Template function might help:
template <int N>
void callbackN() { callback(N); }
and then
vec[0].setCallback(callback<0>);
vec[1].setCallback(callback<1>);
vec[2].setCallback(callback<2>);
vec[3].setCallback(callback<3>);
Since the number of Calculation instances is known at compile-time, you set up something like this to automate things, but not sure if it's worth the effort:
template <size_t Size, typename Idx = std::make_index_sequence<Size>>
class CalcInterface {
std::array<callback_function, Size> m_callbacks { makeCallbacks(Idx{}) };
std::array<Calculation, Size> m_calcs;
protected:
template <size_t N>
static inline callback_function makeCallback() {
return []{ return callback(N); };
}
template <size_t... Seq>
static inline auto makeCallbacks(std::index_sequence<Seq...>) {
std::array<callback_function, Size> arr;
((arr[Seq] = makeCallback<Seq>()), ...);
return arr;
}
static void callback(int id) {
std::cout << "Callback #" << id << " was called\n";
}
public:
CalcInterface() {
for (size_t i=0; i<Size; ++i) {
m_calcs[i].setCallback(m_callbacks[i]);
}
}
void runAll() const {
for (auto& calc: m_calcs) calc.run();
}
};
Example here: https://godbolt.org/z/sWTzn59ce
I am implementing a callback method inside of a class, the currently working implementation uses std::function, however, the STL is not available in the environment I am using. I am seeking to understand how a native implementation would achieve the same result. I have tried using function pointers, this does not work for lambda expression callbacks.
Here is a working example of what I am trying to achieve, using std::function.
#include <iostream>
#include <functional>
using namespace std;
class MyClass {
public:
MyClass(std::function<void(void)> callback): _callback(callback) {}
void call() {
_callback();
}
private:
std::function<void(void)> _callback;
};
class MyOtherClass {
public:
MyOtherClass() {}
MyClass mc = MyClass([this]() { myInt++; });
void callFiveTimes() {
for(int i = 0; i < 5; i++) {
mc.call();
}
}
void printInt() {
cout << myInt << endl;
}
private:
int myInt = 0;
};
int main()
{
MyOtherClass moc = MyOtherClass();
moc.printInt();
moc.callFiveTimes();
moc.printInt();
return 0;
}
So, the question is how can I replace std::function<void(void)> callback such that the program will compile without external libraries.
Update:
Here is an example that requires a bit more work, but achieves the result I am after. I would like to be able to just pass in the callback as the parameter rather than the callback, and callback args param.
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass(void(*callback)(void*), void* callback_arg): _callback(callback), _callback_arg(callback_arg) {}
void call() {
_callback(_callback_arg);
}
private:
void (*_callback)(void*);
void* _callback_arg;
};
class MyOtherClass {
public:
MyClass* mc;
MyOtherClass() {
auto callback=[this](){ myInt++; };
mc = new MyClass([](void* arg){ (*static_cast<decltype(callback)*>(arg))(); },&callback);
}
void callFiveTimes() {
for(int i = 0; i < 5; i++) {
mc->call();
}
}
void printInt() {
cout << myInt << endl;
}
private:
int myInt = 0;
};
int main()
{
MyOtherClass moc = MyOtherClass();
moc.printInt();
moc.callFiveTimes();
moc.printInt();
return 0;
}
I have class with an array of pointers to class methods. However, in the class, when I try to call one of the function in the array, I get an error. Here is the relevant code:
class MyClass
{
typedef void(MyClass::*FunctionPointer)(size_t *i);
void func1(size_t *i) { }
void func2(size_t *i) { }
void func3(size_t *i) { }
void func4(size_t *i) { }
FunctionPointer myFuncs[4] = { func1, func2, func3, func4 };
const std::string funcList[4] = { "FUNC1", "FUNC2", "FUNC3", "FUNC4" };
void doFunc(std::string in)
{
size_t *j = 0;
for (size_t i = 0; i < 4; ++i)
{
if (in == funcList[i]) { this->myFuncs[i](j); }
}
}
};
I have tried omitting "this->" as well as "this->*" and nothing is working. The error I am getting is "expression preceding parentheses of apparent call must have (pointer-to-) function type." Which according to the internet means that I am trying to call something that is not defined as a function. But I am pretty sure that I am?
Thanks
You can if you follow the correct syntax ;)
Get the address of the method using:
&MyClass::func1
Then to resolve the function pointer, do:
(this->*myFuncs[i])
or in full...
class MyClass
{
typedef void(MyClass::*FunctionPointer)(size_t *i);
void func1(size_t *i) { }
void func2(size_t *i) { }
void func3(size_t *i) { }
void func4(size_t *i) { }
FunctionPointer myFuncs[4] = { &MyClass::func1, &MyClass::func2, &MyClass::func3, &MyClass::func4 };
const std::string funcList[4] = { "FUNC1", "FUNC2", "FUNC3", "FUNC4" };
void doFunc(std::string in)
{
size_t *j = 0;
for (size_t i = 0; i < 4; ++i)
{
if (in == funcList[i]) { (this->*myFuncs[i])(j); }
}
}
};
I'm looking to do something only if the class is a specific derived class. That is I have:
class X{
int id;
}
class A: public X{
void run();
}
class B: public X{
int lala;
}
And I want to do something along the line of:
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;
for(int i = 0; i<types.size(); i++){
if(types[i].isType(A)) {types[i].run();}
}
for(int i = 0; i<types.size(); i++){
if(types[i].isType(B)) {var = lala;}
}
}
I do not want class B to have anything equivalent to run(), nor do I want class A to have an equivalent to lala.
I know fortran has a workaround with
select type ( x => var )
class is ( A )
x.run()
end select
But I wasn't sure what my options in C++ were.
Thanks
You are looking for dynamic_cast.
#include <vector>
using namespace std;
class X {
public:
int id;
virtual ~X() = default;
};
class A : public X {
public:
void run() {}
};
class B : public X {
public:
int lala;
};
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;
for(int i = 0; i<types.size(); i++){
if (auto ta = dynamic_cast<A *>(types[i])) {
ta->run();
}
}
for(int i = 0; i<types.size(); i++){
if (auto tb = dynamic_cast<B *>(types[i])) {
var = tb->lala;
}
}
}
Also see it in action here: https://onlinegdb.com/B1d29P5if.
I had to fix a few other problems with the code. Since they are not a part of your question, I won't clarify here, but you are welcome to ask if something is not clear.
EDIT: The above solution has memory leaks, which I didn't fix, as it wasn't required by the question. For completeness, here is the main function with memory leaks fixed (https://onlinegdb.com/ByeOmu9iz):
int main() {
vector<unique_ptr<X>> types;
types.emplace_back(new A);
types.emplace_back(new B);
int var = 0;
for(int i = 0; i < types.size(); ++i) {
if (auto ta = dynamic_cast<A *>(types[i].get())) {
ta->run();
}
}
for(int i = 0; i < types.size(); ++i) {
if (auto tb = dynamic_cast<B *>(types[i].get())) {
var = tb->lala;
}
}
}
Note that this is a C++11 solution.
If you're working with an even older compiler, you'll have to keep using plain pointers as in the original solution, and deallocate the memory manually at the end by calling delete on each element of the vector. (And hope nothing throws an exception before you reach that step.)
You'll also have to replace auto ta with A* ta and auto tb with B* tb.
A modern C++17 solution to this problem is to use a vector of variants, i.e. std::vector<std::variant<A, B>>. You need a modern compiler for this.
Here is a complete example, based on the std::variant documentation:
#include <vector>
#include <variant>
#include <iostream>
class X {
int id;
};
class A: public X {
public:
void run() {
std::cout << "run\n"; // just for demonstration purposes
}
};
class B: public X {
public:
B(int lala) : lala(lala) {} // just for demonstration purposes
int lala;
};
int main() {
std::vector<std::variant<A, B>> types;
types.push_back(A()); // no more new!
types.push_back(B(123)); // no more new!
int var = 0;
for (auto&& type : types) {
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, A>) {
arg.run();
} else {
var = arg.lala;
}
}, type);
}
std::cout << var << '\n'; // just for demonstration purposes
}
As a nice bonus, this solution elegantly gets rid of dynamic allocation (no more memory leaks, no smart pointers necessary).
I have two ideas....
Why not have a shared method that returns a value that gives context as to whether or not it is an A or B? If for example, lala is expected to return only values 0 or greater, you could have void run() instead be int run() and return -1 at all times.
class X {
int id;
virtual int run() = 0; //Assuming X isn't meant to be instantiated
}
class A: public X {
// Return -1 to differentiate between As and Bs
int run() { return -1; }
}
class B: public X {
int lala;
int run() { return lala;}
}
Then you have...
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0, temp = 0;
for( int i = 0; i<types.size(); i++ ) {
if( (temp = types[i].run()) != -1 )
var = temp;
....
}
}
Again, only works if lala would never expect to return a particular range of values.
You could also hide information in X, upon creation of an A or B to keep track of what you have.
class X {
int id;
bool isA;
}
class A: public X {
A() : isA(true) { };
void run();
}
class B: public X {
B() : isA(false) { } ;
int lala;
}
Then you have...
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;
for( int i = 0; i<types.size(); i++ ) {
if( types[i].isA == true ) {
types[i].run();
}
else {
var = types[i].lala;
}
}
Naturally if you expect to add C, D, E, .... it will no longer be worth it, but for only two derived classes it isn't all that bad.
I would justify this based on the fact that users are already going to have to peer into the derived classes to see why they behave so differently for being derived from the same class. I would actually look into whether or not it makes sense for A and B to derive from X based on their interface.
I also wouldn't recommend dynamic_cast(ing) without informing someone that it's one of the more dangerous casts to perform and typically not recommended.
You could use dynamic_cast to check if the base class pointer is convertible to a derived instance.
Another option would be to have a virtual function that returns the typeinfo of the class and thus use that information to cast the pointer to a convertible type. Depending on how dynamic_cast is implemented this could be more performant. Thus, you could use this if you want to try and see whether or not this method is quicker on your platform.
As #Jarod42 noted, you would need to have a virtual function, destructor in this case, for dynamic_cast to work. In addition, you would simply need a virtual destrctor to avoid undefined behavior when deleting the instance.
Example
#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>
struct A {
virtual ~A() {
}
virtual const std::type_info& getTypeInfo() const {
return typeid(A);
}
};
struct B : public A {
virtual const std::type_info& getTypeInfo() const override {
return typeid(B);
}
};
struct C : public A {
virtual const std::type_info& getTypeInfo() const override {
return typeid(C);
}
};
int main()
{
std::vector<A*> data;
data.push_back(new A);
data.push_back(new B);
data.push_back(new C);
for (auto& val : data) {
if (val->getTypeInfo() == typeid(A)) {
std::cout << "A";
}
else if (val->getTypeInfo() == typeid(B)) {
std::cout << "B";
}
else if (val->getTypeInfo() == typeid(C)) {
std::cout << "C";
}
std::cout << std::endl;
}
for (auto& val : data) {
delete val;
}
}
I'm looking for a design pattern which can store vector of pointers and can remove the vector of pointers based on the demand.
This is my existing code path.
### implementation.h
class A {
A() {}
private:
void AggregateMetrics();
void FlushMetrics();
X* x_;
Y* y_;
};
class X {
public:
void CreateFiles(vector<B*> *objects, string path);
};
class B {
B() {
m_ = 0, n_ = 0;
}
private:
int m_, n_;
};
### implementation.cpp
void A::A() {
x_ = new X();
y_ = new Y();
}
void A::AggregateMetrics() {
}
void A::FlushMetrics () {
vector<B*> objects;
x_->CreateFiles(&objects, path);
// In my new code, we are going to move the above two lines
// to AggregateMetrics() and i need to find a way to store
// the vector<B*>objects;
y_->Flush(objects);
return;
}
void X::CreateFiles(vector<B*> *objects, string path) {
CHECK(objects.empty());
for (int i = 0; i < 10; i++) {
objects->push_back(new B());
}
}
Here is my new code:
### implementation.h
class A {
A() {}
private:
void AggregateMetrics();
void FlushMetrics();
X* x_;
Y* y_;
};
class X {
public:
void CreateFiles(vector<B*> *objects, string path);
};
class B {
B() {
m_ = 0, n_ = 0;
}
private:
int m_, n_;
};
class PointerManager {
public:
PointerManager() {}
void SetPointers(vector<B*>& objects);
vector<B*> GetPointers();
private:
vector<B*>objects_;
};
### implementation.cpp
PointerManager::SetPointers(vector<B*>& objects) {
objects_ = objects;
}
vector<B*> PointerManager::GetPointers() {
return objects_;
}
void A::A() {
x = new X();
y = new Y();
mgr_ = new PointerManager();
}
void A::AggregateMetrics() {
vector<B*> objects;
x->CreateFiles(&objects, path);
mgr_->SetPointers(objects);
}
void A::FlushMetrics () {
auto objects = mgr_->GetPointers();
y->Flush(objects);
return;
}
void X::CreateFiles(vector<B*> *objects, string path) {
CHECK(objects.empty());
for (;;) {
objects->push_back(new B());
}
}
I'm basically creating a new class called PointerManager which can hold these pointers after the creation and can return when needed. What would be the ideal design here? Can you guys suggest a design pattern?
I suggest using smart pointer and store them into a container to avoid any memory leak.
Here's the version of your design using smart pointer
implementation.hpp :
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <cassert>
class B {
public:
B() {
m_ = 0, n_ = 0;
}
private:
int m_, n_;
};
class Y{
public:
Y(){}
~Y(){}
void Flush(std::vector<std::unique_ptr<B>>& objects);
};
class X {
public:
void CreateFiles(std::vector<std::unique_ptr<B>> &objects, std::string path);
};
class PointerManager {
public:
PointerManager() {}
void InsertPointer(std::unique_ptr<B> &object);
void SetPointers(std::vector<std::unique_ptr<B>> &objects);
std::vector<std::unique_ptr<B>> &GetPointers();
private:
std::vector<std::unique_ptr<B>> objects_;
};
class A {
public:
A();
void AggregateMetrics();
void FlushMetrics();
private:
X* x_;
Y* y_;
PointerManager* mgr_;
};
implementation.cpp
#include "implementation.hpp"
void Y::Flush(std::vector<std::unique_ptr<B>>& objects){
for(int i =0;i<objects.size();i++){
objects[i].release();
}
}
void X::CreateFiles(std::vector<std::unique_ptr<B>> &objects, std::string path) {
assert(objects.empty());
for (int i = 0; i < 5;i++) {
std::cout << "for loop in CreatesFiles " << std::endl;
objects.emplace_back(new B);
}
}
void PointerManager::InsertPointer(std::unique_ptr<B> &object) {
std::cout << "InsertPointer " << std::endl;
objects_.push_back(std::move(object)); // object now belongs to PointerManager
}
void PointerManager::SetPointers(std::vector<std::unique_ptr<B>> &objects){
for(int i=0;i<objects.size();i++){
this->InsertPointer(objects[i]);
}
}
std::vector<std::unique_ptr<B>>& PointerManager::GetPointers() {
std::cout << "Get Pointers" << std::endl;
return objects_;
}
A::A() {
x_ = new X();
y_ = new Y();
mgr_ = new PointerManager();
}
void A::AggregateMetrics() {
std::cout << "Aggregate Metrics " << std::endl;
std::string path = ".";
std::vector<std::unique_ptr<B>> objects;
x_->CreateFiles(objects, path);
mgr_->SetPointers(objects);
}
void A::FlushMetrics () {
std::cout << "Flush Metrics " << std::endl;
y_->Flush(mgr_->GetPointers());
return;
}
This run fine with CLANG 3.4.2 and g++ 4.9.3 using -std=c++11 flag.
What you are basically asking is: "how do I implement my own memory management using raw pointers?"
And the answer to that is: you don't.
Modern day C++ offers concepts such as smart pointers or unique/shared pointers that take a lot of that "management" burden from the shoulders of your application code.
So the real answer here is: step back, and learn how to use C++ with all the means that are available in 2017; instead of writing code that would have been written like that 15, 20 years ago.