I have a templated class on some object T. T defines two member functions bar and foo
template<class T>
class A {
public:
void f() {
t_.bar();
t_.foo();
}
private:
T t_;
};
Now I would like be able to tell A (ideally at compile time), to call either foo or bar, but not both. So the idea is to tell A at construction time which member function of T to call.
The solution I have currently in place is to pass a callable void callMember(const T& t) { return t.foo(); } in A's constructor to at runtime call the right member, but I'm wondering if there is a better solution?
You can add a bool template parameter to A that tells it which member function of T to call, and then use a constexpr if on that parameter in the body of f:
template<class T, bool Choice>
class A {
public:
void f() {
if constexpr(Choice) // doesn't strictly have to be constexpr
// if T defines both bar and foo
t_.bar();
else
t_.foo();
}
private:
T t_;
};
Now for some type like:
struct S {
void bar() { std::cout << "bar"; }
void foo() { std::cout << "foo"; }
};
you can do:
A<S, true> a;
a.f(); // calls S::bar
A<S, false> b;
b.f(); // calls S::foo
Here's a demo.
I assume its Ok to have instantiations of A be of different type depending on which method is called. If that is the case I suggest to choose between two types rather than two methods.
Say X is the type with the two methods, then you can do this:
struct X {
void foo() {}
void bar() {}
};
struct Xfoo {
X x;
void foobar() { x.foo(); }
};
struct Xbar {
X x;
void foobar() { x.bar(); }
};
Now the template is:
template<class T>
class A {
public:
void f() {
t_.foobar();
}
private:
T t_;
};
And you either instantiate A<Xfoo> or A<Xbar> rather than A<X>.
I suppose you have more than just one type X, then Xfoo and Xbar can be parametrized on the type to be wrapped.
Related
I have class A that needs to invoke the member functions of template class B. Searching around I found this sample code on this site:
#include <iostream>
template<typename T, typename FType>
void bar(T& d, FType f) {
(d.*f)(); // call member function
}
struct foible
{
void say()
{
std::cout << "foible::say" << std::endl;
}
};
int main(void)
{
foible f;
bar(f, &foible::say); // types will be deduced automagically...
}
That came from this answer:
C++ method name as template parameter
But it doesn't do 100% of what I need. How would the above code be re-written so that:
method bar is a public member of a class and not a stand-alone
function
arguments d and f which are getting passed to method bar are
public members of the same class to which bar is a member,
allowing bar to be of type void (void)
object type foible is a class and not a structure (optional)?
[EDIT 1] My own attempt at the rewrite which meets points 1) and 2) is the following, which is wrong:
#include <iostream>
template<class T, void (T::*FType)()>
class foo {
public:
T obj;
FType f;
void bar(void) {
(obj.*f)(); // call member function
} // end bar
}; // end class foo
struct foible
{
void say()
{
std::cout << "foible::say" << std::endl;
}
};
int main(void)
{
foible f;
foo<foible, void (foible::*)()> c;
c.T = f;
c.Ftype = &foible::say;
c.bar(); // types will be deduced automagically...
}
My goal is to have an object of class type 'A' invoke the methods of object of class type 'B', so that when these methods execute the object of type 'B' can use its 'this' pointer to reference its local data. I want to use function pointers inside class type 'A' so that these only need to be specified once, and I don't want one class to have to be derived from another.
You are making that too complicated. Forget about pointers to methods. Currently there is no reason to use them.
Just do something like this:
template<typename F>
void bar(F f) {
doSomething();
f(someArg);
doSomething();
}
int main(void)
{
foible f;
bar([&f](auto x) { f.someMagicMethod(x); } );
return 0;
}
Note this approach is more flexible and readable than playing around with method pointers.
A step by step solution:
all examples uses the following class and foo function
#include <iostream>
class A
{
public:
void foo(){std::cout<<"foo"<<std::endl;}
};
this sample works without template: just calling the calling A::foo with pointer to A and pointer to A::foo:
class B
{
public:
A *a;
void (A::*p)();
void bar()
{
(a->*p)(); //call A::foo
}
};
int main(void)
{
A a;
B b;
b.a = &a;
b.p = &A::foo;
b.bar();
return 0;
}
The following sample added template class T, the pointer to foo method derived from T.
template <class T>
class C
{
public:
T* t;
void (T::*p)();
C(T &o) : t(&o){}
void bar()
{
(t->*p)();
}
};
int main(void)
{
A a;
C<A> c(a);
c.p = &A::foo;
c.bar();
return 0;
}
in the following, the method pointer was templated too, but I don't see how can it be used since you should know how many argument to give it, but anyway:
template <class T, typename F>
class D
{
public:
T* t;
F p;
D(T &o, F pf) : t(&o),p(pf){}
void bar()
{
(t->*p)();
}
};
int main(void)
{
A a;
D<A, void (A::*)()> d(a, &A::foo);
d.bar();
return 0;
}
I am trying to call a member function, possibly given the object pointer, without knowing what class the member function is from. Is this possible?
Basically I want something like the following to work.
class Foo{
public:
Foo(void* object): obj(object) {}
void callFunc(void (*func)()){
obj->*func();
}
private:
void* obj;
};
class Bar{
public:
Bar(): foo(this) {}
void callSomeFunc(){
callFunc(someFunc);
}
void someFunc(){
cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
It looks a lot like an XY-problem. Anyway, let's try to reply to your question as it is.
A function member is bound to the type of the class to which it belongs, unless it's a static one (the latter is treated just like a plain function pointer and you don't even have to pass a pointer to an instance to call it).
Therefore you can make callFunc a function template and let it deduce the type for you:
template<typename T>
void callFunc(void (T::*func)()){
(static_cast<T*>(obj)->*func)();
}
See it up and running on wandbox.
Note that you can incur in errors when you static_cast your obj if its original type (the one you erased to put it in a void *) isn't T.
Here is the full code you can see at the link above:
#include<iostream>
class Foo{
public:
Foo(void* object): obj(object) {}
template<typename T>
void callFunc(void (T::*func)()){
(static_cast<T*>(obj)->*func)();
}
private:
void* obj;
};
class Bar{
public:
Bar(): foo(this) {}
void callSomeFunc(){
foo.callFunc(&Bar::someFunc);
}
void someFunc(){
std::cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
It's an XY problem. Use a std::function and/or a lambda.
#include <functional>
#include <iostream>
class Foo{
public:
template<class F>
void callFunc(F&& f){
f();
}
};
class Bar : public Foo{
public:
Bar(): foo() {}
void callSomeFunc(){
this->callFunc([this]{ someFunc(); });
}
void someFunc(){
std::cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
Although I find the solution provided by #skypjack more elegant, here a solution that templates the Foo-class (not "only" the function) as a whole. Thereby the type of obj is known throughout the Foo-class, which might be an advantage (or may be not).
Further, see also a solution that stores the member together with the associated object. Maybe it's helpful in some way:
#include <functional>
#include <iostream>
template<class T>
class Foo {
public:
Foo(T& obj) : _obj(obj) {}
void callFuncOnObj(void (T::*func)(void)) {
auto fn = mem_fn(func);
fn(_obj);
}
private:
T &_obj;
};
class Bar{
public:
Bar() : d(*this) {}
void callSomeFunc(){
d.callFuncOnObj(&Bar::someFunc);
}
void someFunc(){
cout << "hi Bar1\n";
}
private:
Foo<Bar> d;
};
class Foo2 {
public:
Foo2(std::function<void(void)> f) : _f(f) {}
void callFunction() {
_f();
}
private:
std::function<void(void)> _f;
};
class Bar2{
public:
Bar2() : d(std::bind(&Bar2::someFunc,this)) {}
void callSomeFunc(){
d.callFunction();
}
void someFunc(){
cout << "hi Bar2\n";
}
private:
Foo2 d;
};
int main(){
Bar bar;
bar.callSomeFunc();
Bar2 bar2;
bar2.callSomeFunc();
return 0;
}
Consider the following standard CRTP example:
#include <iostream>
template<class Derived>
struct Base {
void f() { static_cast<Derived *>(this)->f(); }
void g() { static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will stack overflow and segfault
}
If this was regular virtual inheritance I could have mark virtual f and g methods as pure like
struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
and get a compile time error about Foo being abstract. But CRTP offers no such protection. Can I implement it somehow? Runtime check is acceptable too. I thought about comparing this->f pointer with static_cast<Derived *>(this)->f, but didn't manage to make it work.
You can assert at compile time that the two pointers to member functions are different, e.g.:
template<class Derived>
struct Base {
void g() {
static_assert(&Derived::g != &Base<Derived>::g,
"Derived classes must implement g().");
static_cast<Derived *>(this)->g();
}
};
Here is another possibility:
#include <iostream>
template<class Derived>
struct Base {
auto f() { return static_cast<Derived *>(this)->f(); }
auto g() { return static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will not compile
}
For GCC, it gives a pretty clear error message ("error: use of 'auto Base::g() [with Derived = Foo]' before deduction of 'auto'"), while for Clang, it gives a slightly less readable infinitely recursing template instantiation of Base<Foo>::g, with g instantiating itself but eventually ending in an error.
You could use this solution, you can have pure "non-virtual abstract" function, and it maps as much as possible to CRTP this recommendation of H. Sutter:
template<class Derived>
struct Base
{
void f(){static_cast<Derived*>(this)->do_f();}
void g(){static_cast<Derived*>(this)->do_g();}
private:
//Derived must implement do_f
void do_f()=delete;
//do_g as a default implementation
void do_g(){}
};
struct derived
:Base<derived>
{
friend struct Base<derived>;
private:
void do_f(){}
};
You could consider doing something like this instead. You can make Derived a member and either supply it as a template parameter directly each time you instantiate a Base or else use a type alias as I have done in this example:
template<class Derived>
struct Base {
void f() { d.f(); }
void g() { d.g(); }
private:
Derived d;
};
struct FooImpl {
void f() { std::cout << 42 << std::endl; }
};
using Foo = Base<FooImpl>;
int main() {
Foo foo;
foo.f(); // OK
foo.g(); // compile time error
}
Of course Derived is no longer derived so you might pick a better name for it.
Consider the following standard CRTP example:
#include <iostream>
template<class Derived>
struct Base {
void f() { static_cast<Derived *>(this)->f(); }
void g() { static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will stack overflow and segfault
}
If this was regular virtual inheritance I could have mark virtual f and g methods as pure like
struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
and get a compile time error about Foo being abstract. But CRTP offers no such protection. Can I implement it somehow? Runtime check is acceptable too. I thought about comparing this->f pointer with static_cast<Derived *>(this)->f, but didn't manage to make it work.
You can assert at compile time that the two pointers to member functions are different, e.g.:
template<class Derived>
struct Base {
void g() {
static_assert(&Derived::g != &Base<Derived>::g,
"Derived classes must implement g().");
static_cast<Derived *>(this)->g();
}
};
Here is another possibility:
#include <iostream>
template<class Derived>
struct Base {
auto f() { return static_cast<Derived *>(this)->f(); }
auto g() { return static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will not compile
}
For GCC, it gives a pretty clear error message ("error: use of 'auto Base::g() [with Derived = Foo]' before deduction of 'auto'"), while for Clang, it gives a slightly less readable infinitely recursing template instantiation of Base<Foo>::g, with g instantiating itself but eventually ending in an error.
You could use this solution, you can have pure "non-virtual abstract" function, and it maps as much as possible to CRTP this recommendation of H. Sutter:
template<class Derived>
struct Base
{
void f(){static_cast<Derived*>(this)->do_f();}
void g(){static_cast<Derived*>(this)->do_g();}
private:
//Derived must implement do_f
void do_f()=delete;
//do_g as a default implementation
void do_g(){}
};
struct derived
:Base<derived>
{
friend struct Base<derived>;
private:
void do_f(){}
};
You could consider doing something like this instead. You can make Derived a member and either supply it as a template parameter directly each time you instantiate a Base or else use a type alias as I have done in this example:
template<class Derived>
struct Base {
void f() { d.f(); }
void g() { d.g(); }
private:
Derived d;
};
struct FooImpl {
void f() { std::cout << 42 << std::endl; }
};
using Foo = Base<FooImpl>;
int main() {
Foo foo;
foo.f(); // OK
foo.g(); // compile time error
}
Of course Derived is no longer derived so you might pick a better name for it.
I would like to do something like:
class A {
public:
void f();
private:
void g() { };
};
class B {
public:
void f();
private:
void g() { };
};
template<typename T>
void T::f() {
g();
}
int main() {
A a;
B b;
a.f();
b.f();
}
however T::f() does not compile.
Possible workarounds could be making f() non-member:
template<typename T>
void f(T* t);
Or using CRTP: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
But is there no C++ syntax to do as above?
EDIT: I have a big function f() whose code is shared by the 2 classes A and B. A and B have the same interface, which f() uses. However, because we are not using runtime polimorphism (i.e, virtual functions), the corpus of f() needs to be instantiated twice at compile time, once for A and once for B. Templates are made exactly for this purpose. The function f(), in my case, should be template function whose template type is the type of *this.
Free function is the correct answer. You should prefer free functions over member functions anyway, for this exact reason: you extend the interface without intruding on the class.
In this case, a free function with an unconstrained template is a bit ugly, because you only need it to work for two cases, not all cases. You should do something like this:
namespace detail
{
template <typename T>
void f(T* t)
{
// implement stuff
}
}
void f(A* x)
{
detail::f(x);
}
void f(B* x)
{
detail::f(x);
}
Now you can restrict access to that function via overloading.
Here is an example using a free function and retaining the instance.f() syntax. The function needs to be marked as a friend in order to access the private methods:
#include <iostream>
namespace details
{
template<class T>
static void f_impl(T* _this)
{
_this->g();
}
}
class A {
public:
template<class T> friend void details::f_impl(T*);
void f()
{
details::f_impl(this);
}
private:
void g()
{
std::cout << "A" << std::endl;
}
};
class B {
public:
template<class T> friend void details::f_impl(T*);
void f()
{
details::f_impl(this);
}
private:
void g()
{
std::cout << "B" << std::endl;
}
};
int main() {
A a;
B b;
a.f();
b.f();
}