I started learning c++ now. Im quite confuse about this definition. This is just a throwaway code as the actual implementation was on the book I was reading
class A
{
public:
template<class T>
void Hello(void(T::*func)())
{
func(); // Not working. Error term does not evaluate to function taking 0 argument
}
};
class B
{
public:
void funcA()
{
std::cout << "Hello world" << std::endl;
}
// This is called function pointers
void funcB(void(*ptr)())
{
ptr();
}
};
void main()
{
A a;
a.Hello(&B::funcA);
}
First is that what sort of template is that? If it's a template class shouldn't I delcare the template at the top of the class A?
Also why can't I call the func on Hello() like the same as calling a function pointer?
First is that what sort of template is that? If it's a template class shouldn't I delcare the template at the top of the class A?
A::Hello is member function template.
Also why can't I call the func on Hello() like the same as calling a function pointer?
Because the parameter func of Hello is not a function pointer, but a member function pointer. You need an object to call on it. e.g.
template<class T>
void Hello(void(T::*func)())
{
T t;
(t.*func)();
}
LIVE
Related
I have the following code:
class Person {
void func1() {
obj_.function1();
}
void func2() {
obj_.function2();
}
void func3() {
obj_.function3();
}
Object obj_;
};
It's pretty obvious there is a pattern here...
I would like to know if I can call different functions based on template argument.
the functions inside Object are regular member functions.
Is there any way to do something like the following?
class Person {
template <typename Func>
void generic() {
obj_.Func();
}
Object obj_;
};
Another question: Is there a type for function?
I believe it's the key point for it's doable or not.
Thanks
template <auto Func>
void generic() {
(obj_.*Func)();
}
Then foo.generic<&Object::function1>() calls function1.
Prior to c++17:
template <void (Object::*Func)()>
void generic() {
(obj_.*Func)();
}
should work.
I'm searching a solution for this for a few days now. Didn't find any question related enough to answer regrettably so here is my question.
Consider the next code:
// dummy class A
class A {
public:
void aFunction() { // <- this is the function I want to point at
cout << "aFunction() is called\n";
}
};
class B {
public:
template <class Class> // get a function pointer
void setFunction( void (Class::*func)() ) {
p_func = func;
}
void (*p_func)(); // the function pointer
}
int main() {
B obj;
objb.setFunction(&A::aFunction);
return 0;
}
I have a compilation error in setFunction() on p_func = func;:
cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'
And I don't seem to be able to get rid of it in any way. I know it has something to do with those invisible this pointers (__thiscall and __cdecl), but I don't know how to handle these. I tried making the member variable p_func a class template too (void (Class::*p_func)()) so it would have the same structure, but it that seems to be illegal to have 2 class templates in one class (why?), thus isn't the correct solution. This time the compiler complains about:
multiple template parameter lists are not allowed
This method (without the template) works perfectly on global functions (which is the workaround I currently use) and I saw the use of it in a library (sfgui), so it should be perfectly possible.
To have some context over why I'd want this: I'm trying to create a button. This button should be able to call whatever function I'd like. For now, I'd like it to call the start() function of an animation class I'm making.
p.s.: I know this example is useless since I can't run p_func: the function isn't static. I still need to add an object pointer (setFunction( void (Class::*func)(), Class* )), but that does not seem to be a problem. And I know about typedef to make a function pointer more readable, but not with a class template.
EDIT
After some more research I think the answer I need not the answer to this question, but rather another one. For once, I noticed that multiple template <class Class> is in fact allowed. However, it is not allowed on member variables since the compiler can't possibly know which class he'll need to use which probably is the reason for the error
multiple template parameter lists are not allowed
which is an odd description. Thanks anyway for the help, you did gave me a better insight.
You cannot convert a pointer-to-member Class::*func to a normal function pointer. They are of different types.
You should turn this:
void (*p_func)(); // the function pointer
into this:
void (class::*p_func)(); // the function pointer
You could also use a std::function<void()> and use boost::bind to bind it.
std::function<void()> fun = boost::bind(class::member_fun, args);
EDIT
What about making your B class a template so you can do this:
#include<iostream>
class A {
public:
void aFunction() { // <- this is the function I want to point at
std::cout << "aFunction() is called\n";
}
};
template<class T>
class B {
public:
void setFunction( void (T::*func)() ) {
p_func = func;
}
void (T::*p_func)(); // the function pointer
void callfunc()
{
(t.*p_func)(); //call pointer to member
}
private:
T t;
};
int main() {
B<A> obj;
obj.setFunction(&A::aFunction);
return 0;
}
Live Example
I found the complete answer myself while searching for a way to save *objects of an unknown type without using templates or void pointers which has been answered here. The solution is a bit dodgy, because you'll have to create a dummy parent which allows for certain conversions.
The idea is that you create a Parent and every object that is allowed to be pointed to must inherit from it. This way you can create a pointer as Parent *obj which can hold multiple types of objects, but of course only classes that inherit from Parent.
The same applies for function pointers. If you define your pointer as void (Parent::*func)() as member variable. You can ask the user a template function pointer template <class Class> setFunction( void (Class::*f)() ), which can hold any pointer to any class. Now you need to cast the function pointer to the desired class, Parent: static_cast<void(Parent::*)()>(f). Mind that this only works when Class inherits from Parent. Otherwise you'll get a compilation error.
Minimal Working Example
#include <iostream>
using namespace std;
// dummy class Parent
class Parent {};
// class A
class A : public Parent { // Mind the inheritance!
public:
A(int n) : num(n) {}
void print() { // <- function we want to point to
cout << "Number: " << num << endl;
}
int num;
}
// class B, will hold the 2 pointers
class B {
public:
B() {}
template <class Class> // will save the function and object pointer
void setFunction( void (Class::*func)(), Class *obj) {
function = static_cast<void(Parent::*)()>(func);
object = obj;
}
void execFunction() { // executes the function on the object
(object->*function)();
}
void (Parent::*function)(); // the function pointer
Parent *object; // the object pointer
}
int main() {
A a(5);
B b;
b.setFunction(&A::print, &a);
b.execFunction();
return 0;
}
I don't really like this solution. A better solution would be that class B could have a function where it returns a bool when the function needs to be executed. This way you could simply place an if statement in the main-function that executes the desired function.
A a(5);
B b;
while (;;) {
if (b.aTest())
a.print();
}
Where B::aTest() is declared as
bool B::aTest();
Hope this helps anyone that comes across the same problem. So it is perfectly possible but pretty dodgy in my opinion, and I don't encourage people using the first method.
Imagine I have the following free function and functor:
void myFreeFunction(void)
{
cout << "Executing free function" << endl;
}
struct MyFunctor
{
void operator()(void)
{
cout << "Executing functor" << endl;
}
};
As discribed by this answer, I can pass my function or functor as a template argument to another function:
template <typename F>
void doOperation(F f)
{
f();
}
And then call:
doOperation(myFreeFunction);
doOperation(MyFunctor());
So far so good. But what if I want something like the following:
template<typename Callback>
class MyClass
{
private:
Callback mCallback;
public:
MyClass(){}
void execute()
{
mCallback();
}
};
In this case I'm specifing the function/functor when I declare the class but not calling it until later. It works for functors:
MyClass<MyFunctor> myClass1;
myClass1.execute();
But not for functions:
MyClass<myFreeFunction> myClass2;
myClass2.execute();
Compiler says:
error C2923: 'MyClass' : 'myFreeFunction' is not a valid template type argument for parameter 'Callback'
Which is fair enough... but how would you structure this?
Note: I'm aware of std::function and may end up using this. It's measurably slower though so I'm looking at all options.
Thanks,
David
The problem is that freefunction is not a type but a element of a of (int this case a function pointer.
to fix this problem you need to pass the function in, in construction, however you still need to know the exact type.
myclass<call_back_t> my_class(call_back);
EDIT: In c++11 the type can be got from decltype(call_back)
however getting the call back can be troublesome it is often a lot easier to create a generator function
//this should be in the namespace of the class or a static member of it
template<FuncType>
myclass<FuncType> make_class(FuncType func)
{
return myclass<FuncType>(func);
}
//called like
myclass mc=make_class(&my_callback);
Don't for get to alter the constructor
template<typename CallBack>
myclass{
private:
CallBack call_back;
public:
myclass(CallBack call_back_)
: call_back(call_back_)
{}
};
or something like that
I wonder if it is a good practice to have a member template function inside a non-template class in c++? Why?
I'm trying to do something like this
in classA.h:
classA
{
public:
member_func1();
member_func2();
};
in classA.cpp:
template <class T> share_func();
classA::member_func1()
{
call share_func();
}
classA::member_func2()
{
call share_func();
}
I wonder if it is appropriate?
That's a perfectly legitimate use of template functions. Additionally, there's no problem with using templated member functions of a non-template class. For example:
class A {
public:
void say_hello() { cout << "Hello World" << endl; }
template<T> print_it( T arg ) { cout << "Argument: " << arg << endl; }
};
...
A a;
a.say_hello();
a.print_it( 3.14159 );
a.print_it( "A string" );
If the member function logically belongs in your class, and the template type is specific to only that function (and has nothing to do with the rest of your class), I don't see any reason not to do this.
Templating a function is a simple way of overloading it with different argument types, which is perfectly acceptable. In that sense, it's even acceptable to template a single member function in a non-template class, or call a template function from a non-template class. There's nothing ambiguous about it
If you have many methods that have similar signatures, only varying by type, a template method is the way to go:
struct Example
{
void load_from(std::istream&);
void load_from(Database_Table&);
void load_from(Some_Device&);
};
A template method would allow some expansion:
struct Example_Template_Method
{
template <class Input_Source>
void load_from(Input_Source&);
};
The key point here is that a template allows for a method, function or algorithm to operate on different types of objects without changing the algorithm. This can also apply to interfaces as well.
Yes it's good, of course as usual you'd better factorize as much out of the template as possible.
For example:
class Tokens
{
public:
void add(const char* c);
void add(const std::string& s);
template <class T>
void add(T const& t)
{
this->add(boost::lexical_cast<std::string>(t));
}
private:
std::vector<std::string> mTokens;
};
This relieves the tedium of the conversion from the user's lap.
I want to call member function by passing it as template parameter, without using boost is possible. Here is an example off what I tried to do,
class object { void method(); }
{
object object_instance;
...
apply<object:: method>();
...
template<class F>
void apply() { F(object_instance); } // want to call object_instance.F()
}
that does not work, so question is how do I go about binding object method to an object.
Thanks
above is an example, not the real code. I have a bunch of functions differing only in name, but with many parameters, that I want to wrap around in operators.
Something like:
struct foo
{
void bar(void) {}
};
template <typename R, typename C>
R apply(C& pObject, R (C::*pFunc)())
{
return (pObject.*pFunc)();
}
int main(void)
{
foo f;
apply(f, &foo::bar);
}
this.
This is similar to your code, and will allow passing a member function as a template parameter:
class object { public: void method() {} };
object object_instance;
template<void (object::*F)()>
void apply() {
(object_instance.*F)();
}
int main() {
apply<&object::method>();
return 0;
}
As a member function isn't a type or integral value, you can't pass it as a template parameter. You could do what you seem to want by creating a struct which calls the member function, though having object_instance in scope in the template is rather smelly.
What are you actually trying to do?
This example is for rvalue references in c++ox. Does not work on all compilers.
class Sample
{
public:
void fun() { cout << "Sample::fun\n"; }
};
template<typename Function>
void FunCall( Function&& f)
{
f();
}
void RvaluesDemo()
{
FunCall([&]
{
Sample().fun();
});
}