Function pointer inside class point to that class's member function - c++

I am familiar with the function pointer to class member issue, which requires the signature to be ClassName::*FuncPtr, but I have this nuanced problem where I need the function pointer to be to a containing class member:
class F
{
public:
class Container;
typedef void (Container::*FuncPtr)();
F(FuncPtr fp) : m_fp(fp) {}
void Execute() { (*this.*m_fp)(); }
private:
FuncPtr m_fp;
};
class Container
{
public:
Container() : fps(&Container::Func) { }
void Func() { }
private:
F fps;
};
So, basically I want to create an object Container, which will send in its constructor a pointer to one of its member functions to the F object it contains, which should store that function pointer.

You need to move the forward declaration class Container; outside of F. Inside of F, it is declaring F::Container, which is a different type than Container.
Also, (*this.*m_fp)() (alternatively (this->*m_fp)()) won't work at all, as m_fp is expecting a Container object on the left side of .* (or ->*), but this is pointing at an F object instead. So Container will have to pass its this pointer to F's constructor to be stored along with m_fp.
Try this:
#include <iostream>
using namespace std;
class Container;
class F
{
public:
typedef void (Container::*FuncPtr)();
F(Container &c, FuncPtr fp) : m_c(c), m_fp(fp) {}
void Execute() { (m_c.*m_fp)(); }
private:
Container& m_c;
FuncPtr m_fp;
};
class Container
{
public:
Container() : fps(*this, &Container::Func) { }
void Func() { ... }
private:
F fps;
};
Online Demo

Related

Acquiring the templated type of a derived struct element of a base class vector

I have a vector which is a std::unique_ptr of my base struct TextElBaseParams. The elements of this vector consist of structs which are templated TextElParams<T>, these are derived from TextElBaseParams. The derived struct contains a pointer to a variable of type T named var.
I have a function which can only accept TextElParams<T>. I am unable to pass elements from the vector of TextElBaseParams to this function for obvious reasons, so I have the idea that I can somehow convert these elements back to their "derived" type before passing them to the function.
Is this the right way to go about it? If so, what would be the simplest way to implement this? If not, what alternatives could I use to solve this problem?
I am using SFML but the only things to do with that here are irrelevant. Here is a basic outline of my code:
struct TextElBaseParams {
};
template <typename T> struct TextElParams : public TextElBaseParams {
TextElParams( std::string _font = "",
std::string _str = "",
int _fontSize = 1,
sf::Vector2f _position = {0,0},
T *_var = nullptr ) :
font{_font}, str{_str}, fontSize{_fontSize},
position{_position}, var{_var} {}
std::string font;
std::string str;
int fontSize;
sf::Vector2f position;
T *var;
};
I attempt to call a function addElement which takes the TextElParams<T> argument:
std::vector<std::unique_ptr<TextElBaseParams>> tParamsVec; //Filled with derived elements
for(unsigned int i=0; i<tParamsVec.size(); ++i)
addElement(*tParamsVec.at(i));
Prototype for the addElement function:
template<class T>
void addElement(TextElParams<T> &tParams);
addElement works if you directly feed it a TextElParams<T> struct.
That's what virtual functions are for. Make a virtual function in a base class and override it in derived classes. Now if you call a function via the pointer to base class, the corresponding derived function is called. See the example:
class Base {
public:
virtual void invoke() = 0;
virtual ~Base() {}
};
template<typename T>
class Derived;
template<typename T>
void func(Derived<T>& arg) {
std::cerr << "called func with type " << typeid(T).name() << std::endl;
// do smth with arg
}
template<typename T>
class Derived : public Base {
public:
void invoke() override {
func(*this);
}
};
int main() {
std::vector<std::unique_ptr<Base>> vec;
vec.push_back(std::make_unique<Derived<int>>());
vec.push_back(std::make_unique<Derived<double>>());
vec.push_back(std::make_unique<Derived<void>>());
for (const auto& t: vec) {
t->invoke();
}
}
Output:
called func with type i
called func with type d
called func with type v

How to provide a callable object protected access like lambda in C++?

I have a lambda that I need to convert into a callable object so that I can specialize the call operator. My impression has always been that a lambda with an void(auto) signature was equivalent to a callable struct roughly like this:
struct callable {
Foo & capture;
template< typename T >
void operator()( T arg ) { /* ... */ }
}
However, a lambda can access private and protected members when it is declared within a member function.
Here's a simplified example:
#include <iostream>
using namespace std;
class A {
protected:
void a() { cout << "YES" << endl; }
};
class B : public A {
public:
void call1();
void call2();
};
struct callable {
B * mB;
void operator()() {
// This does not compile: 'void A::a()' is protected within this context
// mB->a();
}
};
void B::call1() {
// but then how does this access a() ?!
[&]() { a(); }();
}
void B::call2() {
callable c{ this };
c();
}
int main()
{
B b;
b.call1();
b.call2();
}
Is there any way to emulate that behavior in a callable struct, without declaring it in the header and making it a friend class? That seems problematic because I'm going to have a lot of different callables. I'm also just curious about it, because I was under the impression that lambdas were functionally identical to declaring a struct with a call operator.
Access rights of a lambda capturing this seems to say that the lambda has the same access as a local class. But in my case, I need to emulate a generic lambda, and local classes can't have template member functions.
You can still capture this and &B::a
struct callable {
B* mB;
void (A::*m)();
void operator()() const {
(mB->*m)();
}
};
void B::call2() {
callable c{ this, &B::a };
c();
}
Demo
You can make the struct callable a friend of B without providing a definition for it. Such a declaration doesn't even make the name visible until the real declaration is encountered:
class B : public A {
// ...
friend struct callable;
}
// ERROR: callable isn't visible here:
// callable *foo;
This can be extended to hack in a large number of friends with one declaration if brevity is really important:
class B : public A {
// ...
template<int> friend struct callable;
};
// In implementation:
template<>
struct callable<0> { /* ... */ };
template<>
struct callable<1> { /* ... */ };

Convert class to derived class, without modifying it

I am working with a set of classes A, B, ... These classes are independent except that they have one method in common. Now I want to combine these classes in a vector, to call method in one loop. It seems that the best solution is to make the classes derived classes from some Parent (see below).
Now the question is the following. I want to create a header-only library for each class (a.h, b.h, ...). There I want the classes to be completely independent. Only in the main module I want to 'attach' the classes to a Parent to be able to combine them in a vector. How do I do this? Or do I have to resort to a vector of void* pointers? Or is there another way to combine these classes in a vector?
Classes in list: with parent/child paradigm
Here is what I have been able to do to combine the classes in the vector. Note I specifically want to avoid the parent/child paradigm in the class definitions. But I still want to combine them in a vector.
#include <iostream>
#include <vector>
#include <memory>
class Parent
{
public:
virtual ~Parent(){};
virtual void method(){};
};
class A : public Parent
{
public:
A(){};
~A(){};
void method(){};
};
class B : public Parent
{
public:
B(){};
~B(){};
void method(){};
};
int main()
{
std::vector<std::unique_ptr<Parent>> vec;
vec.push_back(std::unique_ptr<Parent>(new A));
vec.push_back(std::unique_ptr<Parent>(new A));
vec.push_back(std::unique_ptr<Parent>(new B));
for ( auto &i: vec )
i->method();
return 0;
}
Compile using e.g.
clang++ -std=c++14 main.cpp
A possible solution based on type erasure, static member functions and pointers to void that doesn't make use of virtual at all (example code, far from being production-ready):
#include <iostream>
#include <vector>
struct Erased
{
using fn_type = void(*)(void *);
template<typename T>
static void proto(void *ptr) {
static_cast<T*>(ptr)->method();
}
fn_type method;
void *ptr;
};
struct A
{
void method(){ std::cout << "A" << std::endl; };
};
struct B
{
void method(){ std::cout << "B" << std::endl; };
};
int main()
{
std::vector<Erased> vec;
vec.push_back(Erased{ &Erased::proto<A>, new A });
vec.push_back(Erased{ &Erased::proto<B>, new B });
for ( auto &erased: vec ) {
erased.method(erased.ptr);
}
return 0;
}
This can help to avoid using a common base class. See it on wandbox.
As mentioned in the comments, here is a slightly modified version that adds create and invoke methods to reduce the boilerplate for the users.
This is more of a pseudocode, trivial details are omitted.
struct HolderBase
{
virtual void foo() = 0;
};
template <class T>
struct Holder : HolderBase
{
Holder(T* t) : t(t) {}
T* t;
void foo() { t->foo(); }
};
std::vector<HolderBase*> v { new Holder<A>(new A), new Holder<B>(new B) };
You can also have a variant of Holder that holds an object by value (and mix both variants in the same vector freely).
If you have a single method to call, there is a much simpler solution:
A a;
B b;
std::vector<std::function<void()> v { [](){a.foo();}, [](){b.foo();} };
You want to erase the type of the objects and treat them uniformly, so naturally type erasure is the solution.
class with_method_t {
struct model_t {
virtual ~model_t() = default;
virtual void call_method() = 0;
};
template<class C>
class concept_t final : public model_t {
C obj;
public:
concept_t(C const& c) : obj{c} {}
concept_t(C&& c) : obj{std::move(c)} {}
void call_method() override { obj.method(); }
};
std::unique_ptr<model_t> instance;
public:
template<class C>
with_method_t(C&& arg)
: instance{std::make_unique<concept_t<C>>(std::forward<C>(arg))}
{}
void method() { instance->call_method(); }
};
Then have yourself a vector of with_method_t which is a value type. No raw dynamic allocation or de-allocation. The instance is build by forwarding the argument it receives into a small polymorphic container:
std::vector<with_method_t> vec;
vec.emplace_back(A{});
vec.emplace_back(B{});
for ( auto &i: vec )
i.method();

Arrays of Pointers to Abstract Types

I have been experimenting with abstract types.
The code below gives me a desired effect.
class base{
public:
virtual void do_stuff() = 0;
};
class derived: public base{
public:
void do_stuff(){/*stuff*/}
};
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(base* ptr){
ptrs.emplace_back(ptr);
}
};
manager foo;
foo.add(new derived());
Fine and dandy, but it's awkward because the user is not only dealing with pointers, but has to use new without ever calling delete. My question is if there's a way I can implement this where the user of manager doesn't ever have to deal with pointers or new.
foo.add(derived()); //example
My attempts to implement this end up as:
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(base& ref){
ptrs.emplace_back(&ref);
}
};
But, the compiler says no known conversion from 'derived' to 'base&'. I have no idea how to make a reference to base compatible with a reference to derived. How do I get around this?
Pass unique_ptr
Your add function takes ownership of this object. A safe way of passing ownership is to pass unique_ptr.
Using a unique_ptr is fairly flexible because you can construct a shared_ptr from a unique_ptr or if you change your mind in the future you can store the unique_ptr directly.
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(std::unique_ptr<base> ptr){
ptrs.emplace_back(std::move(ptr));
}
};
manager foo;
foo.add(std::make_unique<derived>());
Using a temporary std::unique_ptr you avoid the owning raw pointer that is not exception safe. By using make_unique you can avoid writing new.
Live demo.
Pass a Factory
Another option if the caller really doesn't want to have to deal with any kind of pointer is to pass some sort of Factory that the add function uses to construct the object. The Factory could simply be a static create function on the derived class itself:
using Factory = std::function<std::unique_ptr<base>()>;
class manager{
std::vector<std::shared_ptr<base>> ptrs;
public:
void addUsing(const Factory& factory){
ptrs.emplace_back(factory());
}
};
class derived : public base {
public:
...
static std::unique_ptr<derived> create() {
return std::make_unique<derived>();
}
};
manager foo;
foo.addUsing(derived::create);
Live demo.
You can let your add() function be passed the arguments to be used in the construction of type T, where T is specified as the type of a subclass.
template <typename T, typename... TArgs>
void add(TArgs&&... args)
{
ptrs.emplace_back(std::make_shared<T>(std::forward<TArgs>(args)...));
}
Which can then be called as follows:
bm.add<derived_a>( "hello" ); // derived_a constructor takes a string
bm.add<derived_b>( 42 ); // derived_b constructor takes an int
Full example
#include <string>
#include <vector>
#include <memory>
class base
{
public:
virtual void f() = 0;
};
class derived_a : public base
{
public:
derived_a( std::string const& s ) : s_{ s } {}
void f() override { std::cout << "derived_a::string = " << s_ << '\n'; }
private:
std::string s_;
};
class derived_b : public base
{
public:
derived_b( int i ) : i_{ i } {}
void f() override { std::cout << "derived_b::int = " << i_ << '\n'; }
private:
int i_;
};
class base_manager
{
public:
template <typename T, typename... TArgs>
void add( TArgs&&... args )
{
ptrs.emplace_back( std::make_shared<T>( std::forward<TArgs>( args )... ) );
}
void print() { for ( auto& d : ptrs ) d->f(); }
private:
std::vector<std::shared_ptr<base>> ptrs;
};
int main()
{
base_manager bm;
bm.add<derived_a>( "hello" );
bm.add<derived_b>( 42 );
bm.print();
}
You can't pass a temporary (an r-value) to a non-const reference. Also you try to take the address of that temporary object, which will in the end produce a dangling pointer and undefined behavior.
Assuming you want to pass an object of unknown runtime type to the manager:
One thing you can do is using some sort of polymorphic copy mechanism (like a virtual clone method) and make an internal copy of the object on the heap (it has to be polymorphic, to avoid object slicing).
class base {
public:
virtual void do_stuff() = 0;
virtual shared_ptr<base> clone() const = 0;
virtual ~base()=default;
};
class derived : public base {
int data;
public:
derived() :data(0) {};
derived(const derived& other) :data(other.data)
{};
virtual shared_ptr<base> clone() const override {
return make_shared<derived>(*this);
};
void do_stuff() {/*stuff*/ }
};
class manager {
vector<shared_ptr<base>> ptrs;
public:
void add(const base& obj) {
ptrs.emplace_back(obj.clone());
}
};
int main() {
manager foo;
foo.add(derived());
}
without the clone, it would look something like this:
void add(const base& obj) {
if (typeid(obj)== typeid(derived) ){
ptrs.emplace_back(make_shared<derived>(static_cast<const derived&>(obj)));
}
else if (typeid(obj) == typeid(derived2)) {
...
}
Your original question seems to be concerned over the fact that the user/caller creates a pointer and hands it off and never deletes it. My example below, simply makes it explicit to the user that he can hand it off and forget about it. In otherwords, require the user to pass a shared_ptr...
#include <stdlib.h>
#include <vector>
#include <memory>
using namespace std;
class base{
public:
virtual void do_stuff() = 0;
};
class derived : public base{
public:
void do_stuff(){/*stuff*/ }
};
class manager{
vector<shared_ptr<base>> ptrs;
public:
void add(shared_ptr<base> ptr){
ptrs.emplace_back(ptr);
}
};
int main()
{
manager foo;
shared_ptr<derived> bp(new derived()); //require the user supply a smart pointer
foo.add(bp);
return 0;
}
This is simpler than the other posts, and may not be as forward thinking, but it does not require the derived class to implement additional base members. In many cases, it is may be enough.

c++ how to create a std::vector of functors

class A
{
public:
int x;
//create a vector of functors in B and C here
};
class B
{
public:
struct bFunctor
{
void operator()() const
{
//some code
}
};
};
class C
{
public:
struct cFunctor
{
void operator()() const
{
//some code
}
};
};
void main()
{
A obj;
//iterate through the vector in A and call the functors in B and C
}
My question is what should be the format of the vector in class A for calling functors in B and C? Or is the only way this is possible to have a base functor in A and make the functors in B and C derive from it? Or is there a better approach?
There are essentially two ways to approach this (that I can think of ATM):
Note: I would rename cFunctor and bFunctor to simply Functor in both cases. They are nested inside respective classes and thus such prefix makes little sense.
Type erased
Example of type erasure is std::function.
class A {
public:
int x;
std::vector<std::function<void(void)>> functors;
A() : functors { B::bFunctor(), C::cFunctor() }
{ }
};
If you need the functors to have more advanced behaviour, Boost.TypeErasure any might help.
Polymorphic
Create an abstract functor type.
Make B::bFunctor and C::cFunctor inherit from it.
Store vector of that abstract functor type smart pointers.
struct AbstractFunctor {
virtual void operator()() const = 0;
};
class B {
public:
struct Functor : public AbstractFunctor {
void operator()() const {
//some code
}
};
};
class A {
public:
int x;
std::vector<std::unique_ptr<AbstractFunctor>> functors;
A() {
// this could most probably be shortened with make_unique
functors.emplace_back(std::unique_ptr<AbstractFunctor>(new B::Functor()));
functors.emplace_back(std::unique_ptr<AbstractFunctor>(new C::Functor()));
}
};