Virtual functions, std::function, and non-copyable objects - c++

Below is a simplified, contrived example of what I'm seeing.
Problem
I have a virtual function that accepts a std::function object.
class Foo {
virtual void bar(std::function<void()> &&f);
};
This works fine until I need to capture a non-copyable variable.
auto ptr = std::make_unique<int>();
Foo f{};
f.bar([ptr = std::move(ptr)]() {
// Use ptr...
});
Question
I understand why this doesn't work: std::function doesn't allow non-copyable objects. I also know that, in most cases, the fix would be fo have bar accept a template, something like the following:
template<typename F>
bar(F &&f);
In my specific situation, bar must be virtual. Does anyone know of a workaround?

Use shared_ptr because it can be copied.
Use references or raw pointers and manage the lifetime of the functor manually.
Create visitor classes and use virtual functions (very old-school).
class FooVisitor {
public:
virtual ~FooVisitor() = default;
virtual void Invoke() = 0;
};
class FooVisitorImpl : public FooVisitor {
std::unique_ptr<int> mState;
public:
FooVisitorImpl(std::unique_ptr<int> aState)
: mState(std::move(aState))
{}
void Invoke() final {
// callback code
}
};
// main code
Foo x;
FooVisitor v(std::make_unique<int>(0));
x.bar(v);
// or, if Foo must retain the callback
Foo x;
auto v = std::make_unique<FooVisitor>(/* ... */);
x.bar(std::move(v));

Related

C++ convert list of derived classes to a list of polymorphic pointers

Consider the following code:
class Base {
virtual bool someFunc() = 0;
virtual ~Base() = default;
};
class Derived1 : public Base {
bool someFunc() override { ... }
};
class Derived2 : public Base {
bool someFunc() override { ... }
};
class MyClass {
public:
MyClass(std::vector<Base> derivedClasses) {
for (const auto dClass : derivedClasses) {
m_derivedClasses.emplace_back(std::make_shared<???>(dClass));
}
}
std::vector<std::shared_ptr<Base>> m_derivedClasses;
};
int main() {
std::vector<Base> listOfDerivedClasses = {Derived1(), Derived2()};
MyClass mClass(listOfDerivedClasses)
for (const auto dClass : m_derivedClasses) {
dClass.someFunc();
}
}
Essentially, I have a class that is given a list of derived classes in its constructor, and I want to convert it to a list of pointers to those derived classes so that I can execute the appropriate someFunc() function in main(). I can't seem to figure out how to get this working, do I need some template magic?
EDIT:
I could make the MyClass constructor take a std::vector<Base*> and likely get things to work like that, but it requires the consumer to create the pointers themselves and I'm hoping to shield them from that. In another class I worked on, where I wanted polymorphic behavior, I was able to achieve something like this using templates:
template <typename derivedTypeT, std::enable_if_t<std::is_base_of_v<Base, derivedTypeT>, bool> = true>
MyOtherClass(const derivedTypeT &dClass) : m_dClass(std::make_shared<derivedTypeT>(dClass)) {}
I don't know how I can make this work if the input is a std::vector though, since it obviously could have multiple derived types. Is this something I could do with variadic templates?

Run-Time Checking of a Cast from a void*

Say that I have a void* containing a pointer to an unknown class. I want to use dynamic_cast to do run-time checking on the type of class I actually have. For example:
class Foo {};
void* bar = new Foo;
If I attempt to do dynamic_cast<Foo*>(bar) I get:
'void *': invalid expression type for dynamic_cast
However I need dynamic_cast because in my actual situation I'm not sure that bar is in fact a Foo*.
I've read here that one solution to this is to create a base class for all objects that bar could contain, reinterpret_cast to a pointer to that base class, and then try to dynamic_cast from that object pointer to Foo.
This is difficult for me because the objects that may be stored in bar are not all under my control. (And cause trying to recreate Java gives me heartburn.) Is there another way to do this?
dynamic_cast is use to cast down a polymorphic object to a class that has the type of the object you're trying to cast as it's parent.
void* is completely different from that.
with a pointer to void, you are literally stripping every type information away.
dynamic_cast know that there's a base class and can do type checking through RTTI.
When you cast down a void pointer, you're saying to the compiler: "yeah you know this place in the memory? well, use it as this type" and if the memory is invalid, UB is invoked.
you have three choices here.
Option 1
Use an interface.
Well, a polymorphic base class is the only way to do a dynamic_cast. There is no other way, no hacks, it's the only way. Simple as that.
struct Base { virtual ~Base() = default; };
struct Derived : Base {};
// ...
void test (Base* base) {
auto derived = dynamic_cast<Derived*>(base);
if (derived) {
// derived is valid here.
}
}
Option 2
Identify the type with the pointer
I use a method to have a unique identifier per type and use the identifier to validate the cast. Done without any RTTI
using type_id_t = void(*)();
template <typename T> void type_id() {}
// now we can use a map or a vector.
std::vector<std::pair<type_id_t, void*>> vec;
template<typename T>
void insertToMyVector(T* obj) {
vec.emplace_back(type_id<T>, obj);
}
template<typename T>
T* getObj(int index) {
auto item = vec[index];
return static_cast<T*>(item.first == &type_id<T> ? item.second : nullptr);
}
// ...
int main () {
auto foo = new Foo;
insertToMyVector(foo);
auto maybeFoo = getObj<Foo>(0);
if (maybeFoo) {
// you have a valid Foo here
}
}
Option 3
Generate derived class for any type
This one is quite useful as it can hold any type while keeping type safety. I look like solution 1 but offer more flexibility. The trick it to generate a derived class for any type using templates. The advantage is you can hold any type, but may complexify you cade a bit.
struct Base { virtual ~Base() = default; };
template<typename T>
struct Derived : Base {
Derived(T&& obj) : _obj{std::move(obj)} {}
Derived(const T& obj) : _obj{obj} {}
T& get() {
return _obj;
}
const T& get() const {
return _obj;
}
private:
T _obj;
};
// ...
void test (Base* base) {
auto derived = dynamic_cast<Derived<int>*>(base);
if (derived) {
int i = derived->get();
// derived is valid here, and we can safely access the int
}
}
To ensure dynamic_cast compiles and works, you should create an abstract or interface class with a virtual method.
#include <cassert>
class Bar
{
public:
Bar() = default;
virtual ~Bar() = default;
};
class Foo : public Bar
{
public:
Foo() = default;
virtual ~Foo() = default;
};
int main()
{
Bar* bar = new Foo;
Foo* foo = dynamic_cast<Foo*>(bar);
assert(foo != nullptr);
}
As I understand it you want a polymorphic object but no common base class.
There is already a fairly standard idiom for this - it's called boost::any.
A boost::any carries your object plus some type information. The interface allows you to query the type and to attempt to cast the any to the type you're looking for.
http://www.boost.org/doc/libs/1_59_0/doc/html/any.html

Creating objects only as shared pointers through a base class 'create'-method

I am trying to achieve that certain objects within my application can only be constructed as shared_ptr's by a call to a static method called "create".
Of course I could do this by directly adding the static 'create' method to all the respective class. However, this would mean I have to repeat very similar code in almost all my classes. A macro would work, but I do not find this very elegant.
I came up with an alternative way of doing this by deriving all classes from a templated 'BaseObject' class that implements the 'create' method and returns the pointer. This almost works, except that std::make_shared cannot access the constructor of its child class when it is protected.
The non-solution would be to make the child class constructor public (see (1) in the example below). But now Foo can be normally constructed again and this would defeat the entire point. An alternative solution would be to friend BaseObject in the child class and make use of shared_ptr directly (see (2) in the example).
Both solutions put extra burden on the implementer of the child class. Since they have to either find an alternative way of making the constructor non-public or put a friend declaration. The (2) solution has the additional problem of not being able to use the more efficient make_shared.
My question: is there a better way of doing this?
template<class T>
class BaseObject
{
public:
typedef std::shared_ptr<T> SharedPtr;
template<class... Args>
static typename BaseObject<T>::SharedPtr create(Args&&... args)
{
return std::make_shared<T>(args...);
//return std::shared_ptr<T>(new T(args...)); (2)
}
};
class Foo : public BaseObject<Foo>
{
//friend BaseObject<Foo>; (2)
protected: //public (1)
Foo(int a = 0) : m_foo(a) {}
private:
int m_foo;
};
int main(int argc, char* argv[])
{
Foo::SharedPtr bla = Foo::create(1);
return 0;
}
Update:
They pass-key idiom seems to provide the best solution for me at this moment:
template<class T>
class BaseObject
{
public:
typedef std::shared_ptr<T> SharedPtr;
class Key
{
friend class BaseObject<T>;
Key() {}
};
template<class... Args>
static typename BaseObject<T>::SharedPtr create(Args&&... args)
{
return std::make_shared<T>(Key(), args...);
}
};
class Foo : public BaseObject<Foo>
{
public:
Foo(BaseObject<Foo>::Key, int a = 0) : m_foo(a) {}
private:
int m_foo;
};
The good things:
Only possible to create an object of Foo as a shared_ptr through
Foo::create.
No need to add complex friend declarations in Foo.
std::make_shared still works.
The only problem with this solution is the requirement to have 'Key' as a first argument in the constructor. But I can live with that.
Better is subjective, but I believe it would be a little more intuitive if you would make your constructor private, and std::make_shared a friend function. This way the only function that could create your object would be std::make_shared, and you could write
std::shared_ptr<Foo> ptr = std::make_shared<Foo>(12);
instead of:
Foo::SharedPtr bla = Foo::create(1);
So any future reader of your code would understand what you mean withou actually looking at the Foo class.
UPDATE
I have tried out what I wrote, but did not really work. Here is an answer for a similar question instead, which most likely also aplies for your question:
Using make_shared with a protected constructor + abstract interface
UPDATE 2
Here is how you can make it work (VC++2013)
#include <memory>
using namespace std;
class Foo
{
protected:
Foo(int a = 0) : m_foo(a) {}
private:
int m_foo;
friend shared_ptr<Foo> make_shared<>();
friend class _Ref_count_obj<Foo>;
};
int main()
{
shared_ptr<Foo> foo = make_shared<Foo, int>(12);
return 0;
}
_Ref_count_obj is internally used by make_shared, that's why you need to befriend that too.

Return child class into base class object

I am trying to get my head around some inheritance problem in C++:
Consider a base class Foo() with a method method() and its derived class Bar. Now I override the method in Bar.
class Foo{
public:
double method();
}
class Bar public: Foo
{
public:
double method()
}
And a function like this:
Foo get_bar(){
Bar bar()
return bar
}
Calling the function get_bar() I'd like to be able to call Bar::method()
Foo foo = get_bar();
foo.method() (-> which should be Bar::method)
Is this possible? And if, how? I think I am making a fundamental mistake here which I don't see. Thanks!
To override (not overwrite) a function, it must be virtual:
class Foo {
public:
virtual void method();
virtual ~Foo() = default; // technically optional, but usually needed
};
For completeness, here is the corrected syntax for the derived class:
class Bar : public Foo {
public:
void method() override; // override is optional, but a good idea
};
Polymorphism only works on references and pointers, so your function would have to return one of those, not a base-class object. As it is (once the syntax is fixed), it slices the Bar object to return a copy of its Foo, which would not give you the overridden function that you want.
There's no existing object to return a reference to; so you'll probably have to dynamically create one an return a pointer. Unless you enjoy long debugging sessions, use smart pointers to manage dynamic objects:
std::unique_ptr<Foo> get_bar() {
return std::unique_ptr<Foo>(new Bar); // C++14: make_unique<Bar>();
}
If I understand your question correctly you want get_bar() to return a child class Bar as if it was the base class Foo such that you can subsequently call method on it and it will call Bar::method(). Yes, you can do that. It is called Polymorphism.
In order to achieve this get_bar() needs to return a pointer otherwise you will encounter the slicing problem and won't get the polymorphic behaviour you are looking for. As get_bar() is a factory function transferring ownership to the caller it is preferable to return a smart-pointer like unique_ptr or shared_ptr:
std::unique_ptr<Foo> getBar() {
return std::make_unique<Bar>();
}
Foo::method() needs to be virtual in order to override it in Bar. And in order to destroy Bar properly when the Foo pointer is deleted Foo must have a virtual destructor:
class Foo {
public:
virtual void method();
virtual ~Foo(){}
};
class Bar : public Foo {
public:
void method() override;
};

Pointer to a class member function

Let's say, I've two classes
class A
{
public:
void foo( /* ............. */ );
};
class B
{
public:
void bar();
};
I want to know, if it's even possible to pass to the foo method a pointer of bar method, store it in A and run bar later from A. I should say, that A won't know, what class bar is a member of!
I'd appreciate much if you show me the syntax or some link with not that complicated description of the topic.
DESCRIPTION
I'm designing an observer pattern for C++. I want to subscribe B to some events of A. e.g. this code should be in an instance of B
// pseudo code
A* observable = new A();
observable->addEventListener ( 'eventTitle' , functionName );
And when eventTitle occurs A calls functionName of B
There is a couple of methods how to call a pointer to member function, hiding it's origin:
Use std::function and std::bind:
class B {
double Sqrt(int what) { return std::sqrt((double)what); }
};
// in A:
std::tr1::function<double (int)> fn;
fn = std::tr1::bind(&B::Sqrt, &operations, std::tr1::placeholders::_1);
fn(3.1415);
Use a functor, which will wrap the pointer to member function and the object, on which it's to be called, togeter. (This is a bit complicated, though, and in principle is just a subset of what std::function does).
Derive B from an abstract interface IFn and pass B as IFn reference to Foo. Foo will know what to call - a virtual Do() function of the interface.
How can A use a member function of B without knowing anything about it? To call it, you need an object, which has to be o type B (or subtype), so A must have this knowledge.
If you make bar() a static function, you can use regular function pointer (void (*)()) or std::function<void ()> (boost::function for older C++) - of which I would strongly recommend the latter.
That won't work unless bar is declared as a static member of B. You should take into account that you would need an instance of B in order to call any non-static methods.
(Check the C++ FAQ chapter on pointer-to-member-functions for a deeper explanation.)
UPDATE: if you want to implement an observer pattern, you can declare an interface (pure abstract class), say Observer, that A knows and use pointer-to-member-functions to map your events to the corresponding Observer methods.
Example:
A observable;
observable.addEventListener ( 'eventTitle' , &B::functionName );
B observer;
observable.registerObserver(&observer);
Use something like:
class A
{
public:
void foo( /* ............. */ );
void SetObs(CObs *pObs)
{
m_pObs = pObs;
}
private:
CObs *m_pObs;
};
class B : public class CObs
{
public:
virtual void bar();
};
class CObs
{
public:
virtual void bar() = 0;
};
And whenever you need bar() function call m_pObs->bar(). Also derive all slasses like B from CObs and override the function bar().