Reputation: 227
So I really need a class with the following structure, where the class is templated and arr
is an array of function pointers, but I can't seem to figure out the proper syntax:
--myclass.h--
#include <vector>
template <typename T>
class MyClass {
typedef void (*fptr)(std::vector<T> data);
static void foo(std::vector<T> data);
static void bar(std::vector<T> data);
static void baz(std::vector<T> data);
static const fptr arr[3];
};
--myclass.cpp--
#include "myclass.h"
#include <vector>
template <typename T> void MyClass<T>::foo(std::vector<T> data) { ... }
template <typename T> void MyClass<T>::bar(std::vector<T> data) { ... }
template <typename T> void MyClass<T>::baz(std::vector<T> data) { ... }
template <typename T> MyClass<T>::fptr MyClass<T>::arr[3] = { &foo, &bar, &baz };
If it helps, my ultimate goal is for a fourth member function to call either foo
, bar
, or baz
from the array so I can avoid the overhead of multiple if-else statements (my actual implementation has closer to 50 of these functions). Is there a better way to do this?
Upvotes: 0
Views: 329
Reputation: 7925
You can use std::function
and store them into a vector. Here is what I have come up with so far.
#include <exception>
#include <iostream>
#include <functional>
#include <vector>
template<typename T>
class MyClass {
private:
std::vector<std::function<void(std::vector<T>)>> myFuncs_;
public:
MyClass() = default;
void addFunc( std::function<void(std::vector<T>)> func ) {
myFuncs_.push_back(func);
}
void caller(unsigned idx, std::vector<T> v ) {
return myFuncs_.at(idx)( v );
}
static void foo(std::vector<T> data) {
std::cout << "foo() called:\n";
for (auto& d : data)
std::cout << d << " ";
std::cout << '\n';
}
static void bar(std::vector<T> data) {
std::cout << "bar() called:\n";
for (auto& d : data)
std::cout << d << " ";
std::cout << '\n';
}
};
int main() {
try {
MyClass<int> myClass;
std::vector<int> a{ 1,3,5,7,9 };
std::vector<int> b{ 2,4,6,8,10 };
std::function<void(std::vector<int>)> funcA = MyClass<int>::foo;
std::function<void(std::vector<int>)> funcB = MyClass<int>::bar;
myClass.addFunc( funcA );
myClass.addFunc( funcB );
myClass.caller(0, a);
myClass.caller(1, b);
} catch( std::runtime_error& e ) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
-Output-
MyClass::foo() was called:
1 3 5 7 9
MyClass::bar() was called:
2 4 6 8 10
Not sure if this is exactly what you was looking for. In this example MyClass::caller(...)
takes two parameters, the index into the vector for which function pointer you want, and the parameter or data that the function requires as input.
Upvotes: 0
Reputation: 118057
Move the whole class template into the .hpp file and initialize arr
with the same signature as it was declared:
template <typename T>
class MyClass {
typedef void (*fptr)(std::vector<T> data);
static void foo(std::vector<T> data) {}
static void bar(std::vector<T> data) {}
static void baz(std::vector<T> data) {}
static const fptr arr[3];
};
template <typename T>
const typename MyClass<T>::fptr MyClass<T>::arr[] = { &foo, &bar, &baz };
You may also define arr
directly:
#include <iostream>
#include <vector>
#include <array>
template <typename T>
class MyClass {
typedef void (*fptr)(std::vector<T> data);
static void foo(std::vector<T> data) {
for(int i : data) std::cout << "foo " << i << "\n";
}
static void bar(std::vector<T> data) {
for(int i : data) std::cout << "bar " << i << "\n";
}
static void baz(std::vector<T> data) {
for(int i : data) std::cout << "baz " << i << "\n";
}
public:
static constexpr std::array<fptr,3> arr = { &foo, &bar, &baz };
};
int main() {
MyClass<int> a;
a.arr[0](std::vector<int>(1));
a.arr[1](std::vector<int>(2));
a.arr[2](std::vector<int>(3));
}
Output:
foo 0
bar 0
bar 0
baz 0
baz 0
baz 0
Upvotes: 0
Reputation: 13269
fptr
is declared const
, so define it const
too. Also, because Sort
is a template, you need typename
to refer to MyClass<T>::fptr
.
template<typename T>
const typename MyClass<T>::fptr MyClass<T>::arr[] = { &foo, &bar, &baz };
Side note: you won't be able to put this definition or the definitions of your static functions in a source file since they are templates.
Moreover, consider using using
instead of typedef
, and std::array
instead of a raw array:
using fptr = void (*)(std::vector<T>);
static const std::array<fptr, 3> arr;
// [...]
template<typename T>
const std::array<typename MyClass<T>::fptr, 3> MyClass<T>::arr = { &foo, &bar, &baz };
Is there a better way to do this?
Probably, but I can't say without more details abour what you want to do exactly.
Upvotes: 1