How to pass unique_ptr by reference polymorphically? - c++

I have a pure virtual class Base and some derived classes ChildA (A/B/C etc):
class Base {
...
}
class ChildA : public Base {
...
}
I need specific control of the ownership of these child classes, so I spawn them via factory functions and std::unique_ptr.
At some point during their creation/setup, I need to modify them (not make copies or change ownership) in a manner that is common to all of the derived classes, so I want to use a function that accepts their base type and takes by reference:
void modifyInstance(std::unique_ptr<Base>& baseInst);
But when I try to use this function like so:
bool childAFactory(std::unique_ptr<ChildA>& buffer)
{
buffer = std::make_unique<ChildA>();
modifyInstance(buffer);
}
I get this error:
error: non-const lvalue reference to type 'unique_ptr<Base>' cannot bind to a value of unrelated type 'unique_ptr<ChildA>'
Is it not possible to take advantage of polymorphism in this particular fashion? The only similar threads I can find are where one is trying to pass by value in which case you obviously have to use std::move() and give up ownership.
I would have the function take a regular Base pointer and use unique_ptr::get() but I also need to be able to reset the pointer within the function conditionally (so the pointer and its contents need to be able to be modified, hence passing a unique_ptr by reference).

I'd do this:
bool modifyInstance(Base* baseInst);
bool childAFactory(std::unique_ptr<ChildA>& buffer)
{
buffer = std::make_unique<ChildA>();
if (!modifyInstance(buffer.get()))
buffer.reset();
}
That is, let the factory remain responsible for lifetimes, and just return an error result from modifyInstance() when the object needs to be destroyed.

Related

Return a shared_ptr from a class C++

I have a question which has to do with returning a shared pointer from a class.
Part of my class looks like this:
typedef std::shared_ptr<IBaseInterface> IBaseInterfaceSP;
...
IBaseInterfaceSP getMyInterface()
{
m_spBase = std::make_shared<IBaseInterfaceSP>( m_derivedInterface);
return m_spBase;
}
where both m_derivedInterface and m_spBase are private members of my class, i.e:
private:
IBaseInterfaceSP m_spBase ;
DerivedInterface m_derivedInterface;
Also, DerivedInterface inherits from IBaseInterfaceSP.
getInterface is a public function of my class.
Is this the right way to return a pointer from my class? Will there be any problems with slicing or anything similar?
P.S. I am sorry if something is unclear ( I am not allowed to post all the code here in public, only some parts), if so, just let me know.
I can see several problems with this code.
1. Lazy initialization
Each time you call getInterface, you create a new instance of your IBaseInterface class. As a user of your class, I would not expect this behavior from a method called "get".
I guess you wanted to implement lazy initialization, in which case you would do it like this:
IBaseInterfaceSP getInterface()
{
if (!m_spBase)
{
m_spBase= std::make_shared<IBaseInterface>( m_derivedInterface );
}
return m_spBase;
}
2. Naming conventions
You are instantiating a class called IBaseInterface, which sounds like an abstract class (the "I" prefix was historically used for interfaces). You should probably rename your class so that it doesn't sound abstract. Also, the "I" prefix is redundant with the "Interface" suffix.
However, in what I consider "good" OOP, users do not need to know that you are handing them an interface. There is thus no need for a naming convention that differentiates concrete from abstract classes.
3. Ownership semantics
Shared pointers are meant for shared ownership: when you return a shared pointer, you are telling the users of your class that they will own the returned object, too. Usually, that is not needed. In most cases you would return a non-owning pointer, a.k.a. raw pointer. For example:
IBaseInterface* getInterface()
{
return m_spBase.get(); // Instantiation done elsewhere, for example in constructor
}
4. Slicing
There is indeed slicing happening here. This line:
m_spBase = std::make_shared<IBaseInterface>( m_derivedInterface );
Actually expands to code that contains something equivalent to this:
auto newInstance = new IBaseInterface(m_derivedInterface );
In turn, the line above will call the copy constructor of the IBaseInterface class, whose signature is similar to:
IBaseInterface(IBaseInterface& other)
Thus, m_derivedInterface is interpreted as an IBaseInterface reference in the context of that call. Only the members of IBaseInterface will thus be copied during the call to "new", thereby losing all the information stored in the derived class, DerivedInterface.
All that said, it seems to me that what you really want is direct access to the m_derivedInterface object. What you are doing right now is, you copy the instance into another object and return the new object. I think what you really want is this:
IBaseInterface* getInterface()
{
return &m_derivedInterface;
}
If you insist on using shared ownership, just store a shared pointer to m_derivedInterface instead of a value:
MyClass(Args args)
{
m_derivedInterface.reset(new DerivedInterface(args));
}
std::shared_ptr<IBaseInterface> getInterface()
{
return m_derivedInterface;
}
std::shared_ptr<IBaseInterface> m_derivedInterface;

Passing derived class pointer to function expecting base pointer by reference

I have a key-value container class that holds pointers to heap-allocated objects of a base type. The insert method of the container instantiates one of 2 derived class objects (based on a runtime flag) and inserts it into itself.
I have a Find method with the following signature:
bool Find(int key, Base *&result);
The classes that use of this container know which derived class is actually being stored, because there is a one-to-one mapping between a user of the class and one of the derived types.
So when a user tries to call the Find method as follows:
DerivedA *a = nullptr;
bool found = container.Find(10, a);
I get a compiler error saying that there is no matching function.
So it seems that implicit conversion isn't happening between the base and derived classes. I suspect it has to do with the fact that I'm passing the pointer by reference, but I'm not sure.
What is the "correct" way to achieve what I'm after here?
Thanks!
I suspect it has to do with the fact that I'm passing the pointer by reference
Imagine that Find updates the passed pointer and now it points at a new instance of Base. But the caller still interprets it as a pointer to DerivedA.
Basically the issue is that you can assign
Base* basePtr = &derived;
but not the way around. So if the only guarantee of your Find method is that it finds an instance of Base type, we cannot just assign the pointer to it to DerivedA.
If you do know that your Base class pointer points at DerivedA, you could consider dynamic_cast:
Base* Find(int key);
....
DerivedA* a = dynamic_cast<DerivedA*>(Find(key));
(Returning the pointer might be better, as #juanchopanza comment suggests.)
Add an overload of Find
Base *pi=result;
bool r=Find(key,pi);
result=dynamic_cast<DerivedA *>(pi);
return r;

C++ usefulness of a pointer to non-static method

As I understood pointers to non-static methods, they're no more useful than for providing an alias mechanism for a certain method. For example, having an object with three methods
class Provider
{
public:
int A(int in);
int B(int in);
int C(int in);
}
and a consumer that requires a pointer to a provider method (be it A, B or C). Having a controller that gives a pointer to one of the 3 methods to the so-called consumer, we can write something in the consumer code that uses a Provider instance and the pointer to either A, B or C, depending on what the controller sent.
If this is all that a pointer to a non-static method in C++ can do, is there still a way of providing a more "intelligent" pointer to an object's method, without sending the object along with that method pointer to a consumer? In the affirmative case, what's the idiom/mechanism called (even a way to simulate this qualifies as an answer I'm interested in).
Your concept of member functions pointers is correct in general.
Member functions pointers are actually very useful with conjunctions to such helpers, as std::bind, or std::function. Raw member function pointers are usually ugly.
As for your example,
Your consumer can accept std::function<return_type(args)> and you can pass binding of object and its member function to such consumer.
such structs as std::bind also allows realization of such concepts as partial specialization and currying.
The whole point of a "pointer to member function" is so you can call a named method on any object (of the correct class). So, no, there is no way to "hide" the object reference inside the pointer.
You can always write your own wrappers for stuff like this; that's what the various callback mechanisms for C++ do to give you a more convenient API for the application at hand.
You dont have to glue pointer to object with pointer to method to be called, you can provide pointer to instance any time, ie:
class CClass {
public:
void func(int a) {}
};
///
std::function<void(CClass&, int)> call_func = &CClass::func;
///
CClass cls1;
CClass cls2;
call_func(cls1, 1);
call_func(cls2, 2);

Covariant return type with non-pointer/reference return type

I'm trying to implement a .NET framework like collection class in C++(11). My problem is an invalid covariant type. I have these classes:
template<typename T>
class IEnumerator
{
public:
virtual bool MoveNext() = 0;
//...
};
template<typename T>
class IEnumerable
{
virtual IEnumerator<T> GetEnumerator() = 0;
};
template<typename T>
class List : public IEnumerable<T>
{
public:
struct Enumerator : public IEnumerator<T>
{
Enumerator(List<T> &list)
{
//...
}
// ...
};
Enumerator GetEnumerator()
{
return Enumerator(*this);
}
};
According to me, this is awesome. But it looks impossible to implement it in C++. I get the "Invalid covariant return type" by g++, and as far as I read, the problem is that GetEnumerator might only return a pointer or a reference to Enumerator, and not an object of Enumerator itself.
I'd like to avoid returning a pointer like this:
Enumerator *GetEnumerator()
{
return new Enumerator(*this);
}
because I don't want the caller to bother deleting. Using the temporary object I'd be sure that the object is deleted automatically as it isn't needed anymore. Using references might be even worse.
Am I missing something? Or is there a huge hole in the C++ standard (and language)? I'd really like to achieve something like this.
Thanks in advance.
Covariant value return types cannot be implemented. The problem is that it is the responsibility of the caller to allocate space in the stack for the returned object and the amount of space required for a covariant value return would be unknown at compile time.
This works seamlessly with pointers/references as the returned object is the pointer or reference (rather than the actual derived object), and the size is known at compile time.
After a rather absurd (on my side) discussion with #curiousguy I must backtrack from the previous answer. There is not technical issue that would make covariant value return types impossible. On the other hand, it would have different negative effects:
From a design perspective, the returned object would have to be sliced if called from base (this is where the size of the returned object matters). This is a clear difference from the current model, in the current model the function always returns the same object, it is only the reference or pointer that changes types. But the actual object is the same.
In the general case, covariant value types would inhibit some of the copy-elision optimizations. Currently, many calling conventions, for a function that returns by value, dictate that the caller passes a pointer to the location of the returned object. That allows the caller to reserve the space of the variable that will hold the value, and then pass that pointer on. The callee can then use that pointer to construct in place of the object that will hold the value in the caller context and no copies will be required. With covariant value returned types and because the most derived object created by the final overrider must be destroyed to avoid undefined behavior. The caller would pass a pointer to a location in memory, the trampoline function would have to reserve space for the returned object of the final overrider, then it would need to slice-copy from that second object to the first, incurring the cost of a copy.
At any rate, the actual cost of the operation would not be as much of an issue as the fact that the semantics of the call to the final overrider would be different* depending on what the static type of the reference through which the call is performed.
* This is already the case with the current language definition. For all non-virtual functions, if the derived type hides a member function on the base, then the static type of the returned pointer/reference (which in turn depends on the static type used to call the virtual function) will affect what function gets actually called and the behavior differs.
template<typename T>
class IEnumerable
{
virtual IEnumerator<T> GetEnumerator() = 0;
};
You are trying to return a IEnumerable<T> but it is an abstract base class: it means you promise to construct an object of a class that cannot be instantiated!
Only concrete classes derived from an abstract base class can be instantiated.
You probably intended to return a pointer to such object. Anyway, this is bad design. You do not need to emulate Java in C++.
You just don't do things like that in C++ unless you're using pointers. The .net guys use references so it's pretty much the same stuff.
In C++ you would more likely implement this with concepts rather than inheritance. You should be reviewing "generic programming" ideas. The boost website has a decent introduction: http://www.boost.org/community/generic_programming.html

Factory method pattern implementation in C++: scoping, and pointer versus reference

I've been looking at the example C++ Factory method pattern at Wikipedia and have a couple of questions:
Since the factory method is static, does that mean the newly created object won't go out of scope and have the destructor method called when the factory method exits?
Why return a pointer, as opposed to a reference? Is it strictly a matter of preference, or is the some important reason for this?
Edit 1: The more I think about it, both the reference and the pointer returned will stay in scope because they are referenced outside of the method. Therefore, the destructor won't be called on either one. So it's a matter of preference. No?
Edit 2: I printed out the destructor call on the returned reference, and it doesn't print until the program exits. So, barring further feedback, I'm going to go with the reference for now. Just so I can use the "." operator on the returned object.
Static method is one that can be called without having an instance of the factory. That has nothing to deal wtih the lifetime of the newly created object. You could use a non-static method with the same success. The factory method usually doesn't need any data from an existing object of the same class and therefor doesn't need an existing instance and this is why factorey methods are usually static.
You will use new to create the object that the factory will return. It's usual to return them by pointer. This shows explicitly that it's a new object ant the caller must take care of its lifetime.
I'm thinking there is a greater issue of understanding memory management. The factory method is allocating items on the heap (using new). Items on the heap never get automatically reclaimed (except by modern desktop OSs on process termination). The behavior you are describing is for items on the stack where they are reclaimed when you leave the local scope.
If you return a reference to an object that reference will become invalid when the method goes out of scope. This won't happen with a pointer, since the destructor isn't called.
It is true that static modifies when the value goes out of scope, but only if the variable is declared static, not if the method is declared static.
Your Wiki link says wrong.
There shouldn't be any static method. You can consider Factory Method as Template Method pattern that creates Objects. This method doesn't receive any "Name" parameter and create all the time same type of object.
Often, designs start out using Factory
Method (less complicated, more
customizable, subclasses proliferate)
and evolve toward Abstract Factory,
Prototype, or Builder (more flexible,
more complex) as the designer
discovers where more flexibility is
needed. [GoF, p136]
In the following example Business::makeObject is the factory method
class ObjectBase
{
public:
virtual void action() = 0;
virtual ~ObjectBase(){};
};
class ObjectFirst : public ObjectBase
{
public:
virtual void action(){ std::cout << "First"; }
};
class ObjectSecond : public ObjectBase
{
public:
virtual void action(){ std::cout << "Second"; }
};
class Business
{
public:
void SendReport()
{
std::auto_ptr< ObjectBase > object(makeObject());
object->action();
}
virtual ~Business() { }
protected:
virtual ObjectBase* makeObject() = 0;
};
class BusinessOne: public Business
{
public:
protected:
virtual ObjectBase* makeObject()
{
return new ObjectFirst();
}
};
class BusinessTwo: public Business
{
public:
protected:
virtual ObjectBase* makeObject()
{
return new ObjectSecond();
}
};
int main()
{
std::auto_ptr<Business> business( new BusinessTwo() );
business->SendReport();
return 0;
}
No. Static method - is almost same as global function in class namesapce and with access to private static variables;
Pointers usage is issue of createing objects in heap. They create object in heap for longer object lifetime than create-function scope;
EDIT:
I think wikipedia - is wrong in c++ example.
We have in exmaple - not same implementation as in class diagram or here (http://www.apwebco.com/gofpatterns/creational/FactoryMethod.html)
It will be better if you read about patterns from most trusted sources, e.g: Design Patterns: Elements of Reusable Object-Oriented Software.
The keyword static means different things on a method and on a variable. On a method as in the example it means that it is class global, and you need not have an instance of the class to call it.
To create a new object dynamically you need to use new, or 'a trick' is to assign a temporary object to a reference. assigning a temporary object to a point will not keep that object alive.
So you could do the following, but it is not normally done because you would often want to keep many things created from a factory, and then you would have to copy them rather than simply holding the pointer in a list.
class PizzaFactory {
public:
static Pizza& create_pizza(const std::string& type) {
if (type == "Ham and Mushroom")
return HamAndMushroomPizza();
else if (type == "Hawaiian")
return HawaiianPizza();
else
return DeluxePizza();
}
};
const Pizza &one = create_pizza(""); // by ref
Pizza two = create_pizza(""); // copied
EDIT
Sorry mistake in code - added missing const to ref.
Normally, a temporary object lasts only until the end of the full expression in which it appears. However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself