Initialize Polymorphic Variable on Stack - c++

Coming to C++ with a Java background, I'd like to set up some polymorphic code by initializing a variable of type A with one of two implementations, B or C.
My question is whether there is an easy way to do this on the stack. I have a case where I'm only using A inside the method body, and want it destroyed at the end of the function, so touching the heap is optional.
Here's how I would do it on the heap:
A* a = NULL;
if (p) {
B* b = new B();
b->setSomethingImplementationSpecific();
a = b;
}
else {
a = new C();
}
doSomething(a);
delete(a);
In practice I'd probably pull this out into a factory method, and use an auto_ptr to avoid the delete(a).
This works, but can I do it on the stack? My thought pattern is something like this:
A* a = NULL;
if (p) {
B b;
b.setSomethingImplementationSpecific();
a = &b;
}
else {
C c;
a = &c;
}
doSomething(a);
Now I don't have to bother with delete(a), but doSomething(a) won't work, since the B or C is destroyed when they go out of scope.
I've been trying to figure out a way to do part of it with the ternary operator as well, but I end up both borking up the syntax and taking the address of a temporary -- so am I right that there is no way to do this?
A * const a = &(p ? B() : C());
Advice on whether it's a silly idea to implement polymorphism on the stack in the first place is welcome, but mostly I'm trying to better understand the limits of C/C++ in this area, independently of design sense.

If you are using C++11, you can get "stack semantics" by using a unique_ptr:
std::unique_ptr<A> a = (p ? new B() : new C());
Although the object itself will still be allocated on the heap.
std::auto_ptr<A> is the equivalent idiom in C++03.

You can do this cleanly using std::aligned_union for storage:
template <typename...T>
using storage_t = typename std::aligned_union<0, T...>::type;
and a custom unique_ptr deleter:
struct placement_deleter {
template <typename T>
void operator () (T* ptr) const {
ptr->~T();
}
};
template <typename T>
using stack_ptr = std::unique_ptr<T, placement_deleter>;
Resulting in the usage:
storage_t<B, C> storage;
stack_ptr<A> a;
if (p) {
auto b = new (&storage) B();
a.reset(b);
b->setSomethingImplementationSpecific();
} else {
a.reset(new (&storage) C());
}
doSomething(*a);
See it live at Coliru.

Instead of this original code,
A* a = NULL;
if (p) {
B* b = new B();
b->setSomethingImplementationSpecific();
a = b;
}
else {
a = new C();
}
doSomething(a);
delete(a);
you can do this:
void doSomething( A const& ) {}
void doBeeDoo( B&& b )
{
b.doSomethingImeplementationSpecific();
doSomething( b );
}
void foo()
{
if( p ) { doBeeDoo( B() ); } else { doSomething( C() ); }
}

You could do something like this with boost::optional:
#include <boost/optional.hpp>
void example(bool p) {
boost::optional<B> b;
boost::optional<C> c;
A* a = nullptr;
if (p) {
b = B();
b->setSomethingImplementationSpecific();
a = b.get_ptr();
}
else {
c = C();
a = c.get_ptr();
}
doSomething(a);
}
Note that b and c must have a long-enough lifetime. But only one of them calls a constructor and destructor for B or C.

What you have won't work. b and c will be deleted from the stack by the time you get to doSomething(a);. However, you could do this:
if (p) {
B b;
b.setSomethingImplementationSpecific();
doSomething(&b);
}
else {
C c;
doSomething(&c);
}

Related

How can I use Unique_ptrs with an class object having std::function as argument in the constructor

Problem Description
We have 2 classes A and B. B has the following constructor:
B(std::function<std::unique_ptr<A>()> a)
I am trying to create a unique_ptr as in std::unique_ptr<B> aPtr = std::unique_ptr<B>(new B(std::function<std::unique_ptr<A>())); I can't figure out how to do it. It's not compiling and I can't really explain the error.
How Can I create unique_ptr for class B?
// Online C++ compiler to run C++ program online
#include <iostream>
#include <memory>
#include <functional>
class A {
public:
A(){}
};
class B
{
public:
B(std::function<std::unique_ptr<A>()> a):_a(std::move(a)) {}
private:
std::function<std::unique_ptr<A>()> _a;
};
int main() {
//std::unique_ptr<B> bPtr = std::unique_ptr<B>(new B(std::function<std::unique_ptr<A>()));
return 0;
}
auto bPtr = std::unique_ptr<B>(new B( std::function< std::unique_ptr<A>() > () ));
// need to close the template ^
// need to construct an instance of ^^
You get the same a bit simpler by using std::make_unique:
auto bPtr = std::make_unique<B>( std::function< std::unique_ptr<A>() >() );
// still as above ^^^
Edit: Adjustment to new question version:
You have not yet provided a copy constructor – so you need to store the lambda instead of creating a B instance:
auto l = []() { return std::make_unique<A>(); };
auto bPtr = std::unique_ptr<B>(new B(l));
// or:
auto ptr = std::make_unique<B>(l);
Note that this new edited version provides a factory function to the std::function object (the lambda!), while the initial variants constructed an empty one without function stored inside, so not callable!
You might construct a B by passing a std::function (or value which might convert to).
For example appropriate lambda:
B b{[]() { return std::make_unique<A>(); }};
If you really want std::unique_ptr<B>, then it becomes:
std::unique_ptr<B> b = std::make_unique<B>([]() { return std::make_unique<A>(); });

template deduction/substitution fails on smart pointers

Let's consider this code:
template<typename T>
struct A
{
//...
};
struct B : public A<int>
{
//...
};
template<typename T>
bool validate(A<T>* p)
{
//...
return true;
};
int main()
{
A<int>* pA;
std::cout << validate(pA) << std::endl;
B* pB;
std::cout << validate(pB) << std::endl;
}
It compiles correctly and works as expected. Now, let's say I'd need to refactor the code to use smart pointers instead, then also validate could be changed like this:
template<typename T>
bool validate(std::shared_ptr<A<T>> p)
{
//...
return true;
};
int main()
{
std::shared_ptr<A<int>> pA = std::make_shared<A<int>>();
validate(pA); //it compiles correctly
std::shared_ptr<B> pB = std::make_shared<B>();
validate(pB); //it FAILS to compile
}
You can verify that here.
What is the reason behind this?
What is the best way to solve this problem without modifying A or B?
This is because it requires to perform custom casting from shared_ptr<B> to shared_ptr<A<int>> to disambiguate the template function parameters. Disambiguation of template functions parameters doesn't even attempt to do type casting (aside from some basic stuff).
It is simply not practictical to even try. Well, theoretically there could've been a partial solution that specify which custom castings to try but there isn't. Just use SFINEA and disambiguate it yourself instead of asking compiler to do it for you.
In general you should avoid smart pointers if the called function does not change ownership! Use your raw pointer function.
You force a Generic type of A in function validate. Inheritance is not considered here.
If you ignore inheritance it could look like:
template<typename T>
bool validate(std::shared_ptr<T> p)
{
return true;
}
See on Godbolt
To force a base class I would introduce a Typetag.
The ways around this I can see possible are:
Alternative 1)
std::shared_ptr<B> pB = std::make_shared<B>();
//... do your type B related operations through pB
validate(std::shared_ptr<A<int>>(pB));
Alternative 2)
template<typename T>
bool validate(A<T> const & a)
{
//...
return true;
}
int main()
{
std::shared_ptr<A<int>> pA = std::make_shared<A<int>>();
validate(*pA);
std::shared_ptr<B> pB = std::make_shared<B>();
validate(*pB);
}
Alternative 3)
template<typename T>
bool validate(std::shared_ptr<A<T>> p)
{
//...
return true;
}
template<typename T>
bool validate(std::shared_ptr<T> p)
{
//...
return true;
}
int main()
{
std::shared_ptr<A<int>> pA = std::make_shared<A<int>>();
validate(pA); // it uses bool validate(std::shared_ptr<A<T>> p)
std::shared_ptr<B> pB = std::make_shared<B>();
validate(pB); // it uses bool validate(std::shared_ptr<T> p)
}
but that implies that the function might extend to many other types, and it is not necessarily a desired behaviour (maybe?).
Any other suggestions guys?
It would be cool if someone knows why the code in the question doesn't work in the first place.

How to pass a nullptr?

Below is a simplified example of the code I'm working on. There's a function that takes class A pointer as an argument. I want to pass a pointer that has been initialized as nullptr. Without initializing it to some garbage temporary value first, is it possible to pass the nullptr?
class A
{
// stuff
};
class B
{
public:
A* pA1;
A objA;
std::vector<A*> vecB;
B() : pA1 (nullptr) { vecB.push_back(&objA); }
};
void function(A* p);
A* pA2;
int main()
{
B objB;
pA2 = objB.vecB[0];
function(objB.pA1);
return 0;
}
void function(A* p)
{
p = pA2;
}
In a comment, you said:
The point of the function is to make this happen: objB.pA1 = pA2
I think what you need to do is pass a reference to the pointer, instead of passing a pointer by value. Use:
void function(A*& p) // The argument type needs to be "A* &", not "A*"
{
// Now, the change will be visible in the calling program.
p = pA2;
}
Yes. Any raw pointer type can be assigned and therefore initialised with the nullptr value. Example:
static A* pA2 = nullptr;
aschepter has given me the answer in a comment, thank you very much.
void function(A* p)
should be
void function(A*& p)

automatic calling custom converter of raw pointers A* <-> B*

Is it possible to define a custom converter (converter1<T> and converter2) between different types of raw pointer A* and B*,
then make all functions (fa() and fb()) in a certain class
use an appropriate converter (converter1<T> or converter2)?
In short, I want the program to convert A* to B* and vice versa USING my custom functions.
I wish it would do that automatically for my convenience.
class Manager{
void fb(B* b){ /** something complex */ }
void fa(A* a){ /** different thing complex */ }
void testCase(){
A* a= ... ;
fa(a);
fb(a); //automatic convert to B* using "converter2" (wish)
B* b= ... ;
fa(b); //automatic convert to A* using "converter1" (wish)
fb(b);
}
template<class T> T* converter1(B* b){ //hardcoded, non-static.
return this->getId<T>(b);
//^^^ just an example to show how custom it is,
// currently T=A
}
B* converter2(A* a){ //hardcoded
return a->getB();
//^^^ just an example to show how custom it is.
}
}
The real case has many A - A1, A2, A3 and so on.
A and B are not derived from each other.
I wish there is a way. I think about constructor of pointer.
No this is not possible.
Pointers are built-in types and only built-in conversions between built-in types exist. User-defined conversions only work for user-defined class types.
You may want to switch to your own brand of smart pointers to handle this.
through references (or smart pointers) it's more possible:
struct A {};
struct B {};
A& convert_to_a(A& a) { return a; }
A convert_to_a(B const& b) {
// makes a new A from a B
return A();
}
B& convert_to_b(B& b) { return b; }
B convert_to_b(A const& a) { return B(); }
struct Manager
{
template<class T>
void fa(T&& t) {
auto&& a = convert_to_a(t);
// do something with a
(void)a;
}
template<class T>
void fb(T&& t) {
auto&& b = convert_to_b(t);
// do something with b
(void)b;
}
};
int main()
{
A a;
B b;
Manager m;
m.fa(a);
m.fb(a);
m.fa(b);
m.fb(b);
}
It is not possible the way you want it.
Anyway, you can use a catch-all function and a bunch of traits to simulate it.
It follows a minimal, working example:
#include<iostream>
struct A {};
struct B {};
template<typename T>
A* ToAConverter(T*) = delete;
template<>
A* ToAConverter<B>(B *b) {
// just an example
return new A;
}
struct Manager{
void fa(A* a){ std::cout << "fa" << std::endl; }
template<typename T>
void fa(T *t) {
std::cout << "convert and forward" << std::endl;
fa(ToAConverter<T>(t));
}
void testCase(){
A *a = new A;
fa(a);
B *b = new B;
fa(b);
}
};
int main() {
Manager m;
m.testCase();
}
In case you haven't defined a converter for a specific type, you'll receive a compile-time error.
As you can see, you have no longer to call explicitly the converter when you invoke fa.

Is it possible to detect if the object that a bound member function refers to is deleted or destroyed

I am exploring the use of std::function and std::bind. I see that you can bind a member function, for example:
class A{
int c_ = 10;
public:
int add(int a, int b){
return a + b + c_;
}
};
int main(){
A* p_a = new A;
std::function<int()> f = std::bind(&A::add, p_a, 1, 1);
printf("%i\n", f()); // yields "12" (1 + 1 + 10)
delete p_a;
printf("%i\n", f()); // yields derpy numbers, no errors thrown.
}
Is there a way to detect if p_a has been deleted?
My solution to do this is having a wrapper class that holds the function and a weak_ptr to the object. I am just wondering if there is a more elegant way to do this.
std::bind can accept smart pointers, so you can simply pass std::shared_ptr<A> to it.
std::shared_ptr<A> p_a(new A);
std::function<int()> f = std::bind(&A::add, p_a, 1, 1);
Note, that the functor will own the object: the object will live as long as the functor lives. If you don't want such behavior, then your solution with a weak_ptr wrapper is nice.
struct A{
int c_ = 10;
int add(int a, int b){
return a + b + c_;
}
};
template<class T>
std::weak_ptr<T> weak( std::shared_ptr<T> const& sp ) { return {sp}; }
int main(){
auto p_a = std::make_shared<A>();
std::function<int()> f = [w_a = weak(p_a)]() {
if (auto p_a = w_a.lock())
return p_a->add(1,1);
throw w_a;
}
printf("%i\n", f()); // yields "12" (1 + 1 + 10)
p_a.reset();
try {
printf("%i\n", f()); // yields derpy numbers, no errors thrown.
} catch( std::weak_ptr<A> wp ) {
printf("object deleted\n");
}
}
live example.
in general, in C++ you don't pay for what you don't use.
Tracking the lifetime of objects has a cost. If you want to track the lifetime of objects, you can use a shared_ptr or weak_ptr to the (free-store) allocated object, or use a weak_ptr to a shared_ptr (uniquely) owned by the object to indicate its lifetime is over.
The above is an implementation using C++14 lambdas to capture the object's shared pointer as a weak ptr, and give defined behavior (a throw of a copy of said weak pointer) if it has been deleted.
A lifetime token looks like:
using lifetime_token = std::weak_ptr<void>;
struct has_lifetime {
has_lifetime():token(std::make_shared<char>()) {}
has_lifetime(has_lifetime const&o):has_lifetime() {} // not default
lifetime_token get_lifetime() const {
return token;
}
private:
std::shared_ptr<void> token;
};
inheriting from has_lifetime gives you a get_lifetime() member that exists for as long as you do (it is destroyed by your destructor, and can no longer be .lock()d).
This is an easier pattern to follow if you cannot modify the ownership semantics of the original class. Simply .lock() the lifetime_token of the object to determine if it is still alive.