Is this proper usage of a unique_ptr? - c++

from what I've discerned by reading through most of the questions on here that pop up when looking up unique pointers, this seems to me like it should provide the behavior described by the Builder pattern.
I want any instance of Builder (or its sub-classes, since it doesn't implement any procedures for modifying the object under construction) to own the object under construction until Close returns the unique pointer to the caller, at which point the caller takes ownership.
Builder.h
template <class type> class Builder
{
public:
~Builder();
unique_ptr<type> Close();
protected:
Builder();
unique_ptr<type> _uptr;
};
Builder.cpp
template<class type> Builder<type>::Builder()
{
uptr = make_unique<type>();
}
template<class type> Builder<type>::~Builder()
{}
template<class type> unique_ptr<type> Builder<type>::Close()
{
return uptr;
}
Do I understand the semantics of passing a unique pointer by value?
(includes and namespaces omitted for brevity / legibility)

std::unique_ptr cannot be copied. Instead, you will have to move uptr in order to properly transfer ownership of the underlying pointer.
template<class type> unique_ptr<type> Builder<type>::Close()
{
return std::move(uptr);
}

Do I understand the semantics of passing a unique pointer by value?
You can move from a unique_ptr: std::move(this->_uptr)
Be cautious with moves as they invalidate the contents of the original object.
I've completed your example to exemplify the threat:
#include <iostream>
#include <memory>
template<typename T> class Builder
{
public:
virtual ~Builder() {}
std::unique_ptr<T> Close();
protected:
Builder() {}
std::unique_ptr<T> _uptr;
};
class IntBuilder: public Builder<int>
{
public:
IntBuilder() : Builder<int>() {
this->_uptr = std::unique_ptr<int>(new int);
}
void setValue(int x) {
*(this->_uptr) = x;
}
std::unique_ptr<int> Close() {
return std::move(this->_uptr);
}
};
int main() {
IntBuilder b;
b.setValue(3);
auto i = b.Close();
std::cout << *i << std::endl; // OK
auto i2 = b.Close();
std::cout << *i2 << std::endl; // Segmentation fault
}
Although this->_uptr was moved within IntBuilder::Close(), the compiler will not warn you about the Segfault potential.
Furthermore I'd recommend just using T Builder<T>::Close() instead of unique_ptr<T> Builder<T>::Close() as the latter just limits flexibility of the class.
Also why not have sub-classes manage the instance they're creating. If the instance they're creating cannot be mutated the sub-class needs to store information about the instance until its creation (at Close()) and will unnecessarily carry along the unique_ptr<T>.
Here's how I'd alter the Builder class:
template<typename T> class Builder
{
public:
virtual ~Builder() {}
T&& Close();
protected:
Builder() {}
};

Related

is it possible to create pointers of derived classes using their base class constructor without modifying the layout of the derived classes?

consider this layout:
#include <memory>
#include <vector>
struct data{};
struct task {
data* data_ptr = nullptr;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
a task has access to data. The derived classes must implement their indivial work() routine.
Now task_collection stores the data and a vector of task pointers, and instances of derived classes can be added to that vector:
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>());
this->tasks.back()->data_ptr = &this->data;
}
};
int main() {
task_collection t;
t.add<special_task>();
}
now this works very well. However, I am wondering if I can replace the data* data_ptr with a reference as it seems more appropriate here and it also replaces the many -> with .s
However, it seems impossible to implement this without changing the layout of special_task as the reference requires a constructor in the base task class and derived classes dismiss their base constructors:
struct task {
task(data& data) : data_ref(data){}
data& data_ref;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>(this->data)); //Error!
}
};
It gives this error:
Error C2664 'special_task::special_task(const special_task &)': cannot convert argument 1 from 'data' to 'const special_task &'
I am aware that this can be "solved" by adding
using task::task;
to every derived class, as now it now finds the appropriate constructor. This is not really a solution though, as there are hundreds of derived classes potentially, written by multiple people. If one instance of using task::task; is missing it could cause headaches. The additional lines of code also negate the benefit that comes from using reference instead of pointers.
So is there any way to implement task::data_ref as a reference where only task_collection or task are modified, but not any of the derived classes?
ITNOA
If owner of question can accept some of time using get() instead of . to access to the data, he can use std::reference_wrapper instead of raw reference to resolve rebinding problem.
#include <memory>
#include <vector>
#include <functional>
struct data{};
static data empty_data;
struct task {
std::reference_wrapper<data> data_ptr = empty_data;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>());
this->tasks.back()->data_ptr = std::ref(this->data);
}
};
int main()
{
task_collection t;
t.add<special_task>();
}
For using the data, you can for example behave like below
data temp_data = t.tasks.back()->data_ptr;
As you can see in How to correctly use std::reference_wrappers, Class std::reference_wrapper implements an implicit converting operator to T&:
constexpr operator T& () const noexcept;
So the implicit operator is called when a T (or T&) is required, and you do not need using get() function, For instance
void f(some_type x);
// ...
std::reference_wrapper<some_type> x;
some_type y = x; // the implicit operator is called
f(x); // the implicit operator is called and the result goes to f.
So you have to sometimes to using .get(). instead of always using ->

Create a smart-pointer-to-base-class from a reference

I have a container which store a vector of smart-pointer-to-base-class, and I'd like to populate it via a method without requiring my users to also create that smart pointer:
class Base {
// ...
};
class Derived: public Base {
// ...
};
class Collection {
private:
vector<unique_ptr<Base>> pointers;
public:
void add(Base&& value) // #1
{
pointers.push_back(????);
}
void add<typename T>(T&& value) // #2
{
pointers.push_back(????);
}
};
int main() {
Collection collection;
collection.add(Derived("Data")); // #3
}
What's the correct way to do this, if at all? It's clear that I could use make_unique and emplacement, except that I'm concerned that the derived content won't be moved correctly.
It's possible I've spent too much time in Rust land, where moves of this kind are pretty commonplace, so let me know if I'm way off base here. Ideally, the interface looks like my #3 point up there, where the function can be called with a literal of the derived type without any extra boilerplate related to allocation or anything. I'd be find if the solution ends up being to make Collection::add generic.
You should probably stick to the template, yes. You then get
class Collection {
std::vector<std::unique_ptr<Base>> pointers;
public:
template<typename T>
void add(T &&value) {
pointers.emplace_back(std::make_unique<std::remove_reference_t<T>>(std::forward<T>(value)));
}
};
int main() {
Collection c;
Derived d;
c.add(d); // works with lvalues (copying)
c.add(std::move(d)); // or rvalues (moving)
Base b;
c.add(b);
c.add(std::move(b));
}
However, it might be more useful to provide an "emplace", which constructs an object out of arbitrary arguments (as provided by all the standard containers)
class Collection {
std::vector<std::unique_ptr<Base>> pointers;
public:
template<typename T, typename... Ts>
void emplace(Ts&&... args) {
pointers.emplace_back(std::make_unique<T>(std::forward<Ts>(args)...));
}
template<typename T> // still useful for conciseness (don't have to specify T)
void add(T &&value) {
this->emplace<std::remove_reference_t<T>>(std::forward<T>(value));
}
};
So you can further do
int main() {
Collection c;
Derived d;
c.add(d); // works with lvalues
c.add(std::move(d)); // or rvalues
c.emplace<Derived>(); // or can give arguments directly (assuming a default constructor, in this case)
Base b;
c.add(b);
c.add(std::move(b));
c.emplace<Base>();
}
A complete example on Godbolt.

Invoke a templated member from a c-function using void pointer

My c++ code has to work with an underlying c-library. I have a c++ object that looks somewhat like this:
template <typename T>
class MyClass
{
public:
explicit MyClass(int x)
: mVar(x)
{
}
private:
int mVar;
};
Later in my c++ code I do the following:
auto p = new MyClass<int>(10);
call_c_lib_function((void*) p);
The c function saves the pointer 'p' in a larger c-structure. Later when the large
c object is getting destroyed, it invokes the delete handler.
void
c_delete_handler(void* data)
{
// data is holding the pointer value 'p' from above.
}
Since the object is getting destroyed, I need to free the object that allocated.
Per the c++ spec, 'delete void_ptr' is undefined since it doesn't know how to
invoke the appropriate destructor. How do I invoke delete on the appropriate
template object?
One solution I could think of was to create a wrapper structure around my MyClass pointer.
struct Wrapper {
enum template_type {
template_int,
template_double,
template_string,
...
};
int template_type;
void* obj_ptr;
};
before callign the call_c_lib_function, I'd do the following:
auto p = new MyClass<int>(10);
auto w = new Wrapper()
w.template_type = Wrapper::template_int;
w.obj_ptr = (void*) p;
call_c_lib_function((void) w);
and now in the delete handler, I can do the following:
void
c_delete_handler(void* data)
{
Wrapper* w = (Wrapper*) data;
switch (w->template_type) {
case Wrapper::template_int:
delete (MyClass<int>*) w->obj_ptr;
break;
case Wrapper::template_double:
delete (MyClass<double>*) w->obj_ptr;
break;
...
}
}
Is this a correct approach? is there a better alternative?
Would appreciate any inputs. Thanks.
Instead of using Wrapper, use a base class, if that's an option.
class MyBase
{
public:
virtual ~MyBase() {};
};
template <typename T>
class MyClass : public MyBase
{
public:
explicit MyClass(int x) : mVar(x) {}
private:
int mVar;
};
and then
void c_delete_handler(void* data)
{
Base* basePtr = reinterpret_cast<Base*>(data);
delete basePtr;
}
This approach obviates the need for keeping track of whether MyClass was instantiated using int, double, std::string, or ....

Is there a way to prevent assignment of pointers?

A tricky question. If would like to write a function that returns a pointer to some IFoo object, is it possible to prevent the assignment of this pointer?
I do not want to make IFoo a singleton and I can hide or delete the copy and assignment operators, but does C++ actually allow a pattern, where I explicitly have to call somebody else to obtain an object?
The background question is: I am thinking about some sort of dependency container, where you should always ask the container to get some IFoo * (pointer for the sake of polymorphism). The user should never be able to save it to some local variable or member to avoid a stalled reference to it. (For scenarios where the container is instructed to return no longer Foo, which is derived from IFoo but Bar)
Edit for clarification, although user R Sahu already said that is not possible.
Indeed the example of Mark B was a perfect illustration of what I wanted to prevent:
IFoo* foo_ptr_I_will_keep_forever = obj->getIFoo();
When I wouldn't have interfaces but only explicit instance of types I could return a reference, which given a private operator= and copy ctor would suffice.
Your title says:
Is there a way to prevent assignment of pointers?
No, you can't prevent that if your function returns a pointer.
However, if you return a handle, which can be a pointer to a type that is only forward declared or an integral value that can be used to come up the real object, and make sure that all the real functionality works with the handle, then you can have more freedom over when you can delete the real object without the risk of leaving the client code with a dangling pointer.
Here's a simple program that demonstrates the concept.
#include <iostream>
#include <set>
// Foo.h
struct Foo;
using FooHandle = Foo*;
FooHandle createFoo();
void fooFunction1(FooHandle h);
void fooFunction2(FooHandle h);
// Test Program
int main()
{
FooHandle h = createFoo();
fooFunction1(h);
fooFunction2(h);
fooFunction1(h);
return 0;
}
// Foo implementation.
namespace FooImpl
{
std::set<Foo*>& getLiveFooObjects()
{
static std::set<Foo*> liveObjects;
return liveObjects;
}
bool isValid(Foo* h)
{
return (getLiveFooObjects().find(h) != getLiveFooObjects().end());
}
}
using namespace FooImpl;
struct Foo {};
FooHandle createFoo()
{
FooHandle h = new Foo{};
getLiveFooObjects().insert(h);
return h;
}
void fooFunction1(FooHandle h)
{
if ( isValid(h) )
{
std::cout << "In fooFunction1.\n";
}
else
{
std::cout << "Ooops. The handle is no longer valid.\n";
}
}
void fooFunction2(FooHandle h)
{
std::cout << "In fooFunction2.\n";
delete h;
getLiveFooObjects().erase(h);
}
Output:
In fooFunction1.
In fooFunction2.
Ooops. The handle is no longer valid.
Give them back an object (that they can store if they want) that always looks up the real one via private (friend) interfaces.
For example, an IFooCaller that implements IFoo by getting the current IFoo and forwarding all calls to it.
A middle ground answer that would prevent accidentally storing a pointer to a particular implementation, but wouldn't prevent someone from doing it on purpose:
template <typename T> class service_wrapper;
class service_manager
{
template <typename T> friend class service_wrapper;
public:
template <typename T>
service_wrapper<T> get() const;
private:
template <typename T>
T* get_instance() const;
};
template <typename T>
class service_wrapper
{
friend class service_manager;
public:
T* operator->() const;
private:
service_wrapper(service_manager const & p_sm) : sm(p_sm) { }
service_manager const & sm;
};
template <typename T>
T* service_wrapper<T>::operator->() const
{
return sm.get_instance<T>();
}
Your manager only dispenses instances of service_wrapper<T>. The operator-> implementation allows invoking on the service using wrapper->method(...);, and always fetches the implementation pointer from the service manager.
This can be circumvented like:
T *ptr = sm.get<T>().operator->();
But that's not something you can accidentally do.

How to store templated objects of different type in container?

Assuming I have a vector (or list or whatever container might be more suitable here) that I would like to store multiple objects (or pointers) of a templated type in:
std::vector<MyClass<double>> v;
// std::vector<MyClass<double> *> v;
Unfortunately, I want to store different templated objects in this container (and I need to access them ideally at constant time).
My first intuition was to create some sort of WrapperClass around MyClass that would internally manage any MyClass as a member variable, but it's not clear to me how I could pass along the appropriate type through to MyClass:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
template<typename T>
class MyClass
{
public:
MyClass() {}
~MyClass() {}
};
// templating this of course works, but it doesn't solve my problem
template<typename T>
class WrapperClass
{
public:
WrapperClass()
{
m_object = MyClass<T>();
}
~WrapperClass() { }
private:
MyClass<T> m_object;
};
int main()
{
WrapperClass<bool> tmp = WrapperClass<bool>();
std::vector<WrapperClass<bool> *> v;
return 0;
}
So is there (A) a different container than vector that I could be using for this problem or (B) a way to select the type of MyClass in WrapperClass inside the constructor? I was thinking of something along the lines of:
class WrapperClass2
{
public:
WrapperClass2(unsigned int typeId)
{
switch (typeId)
{
case 0: m_object = new MyClass<bool>();
case 1: m_object = new MyClass<int>();
case 2: m_object = new MyClass<float>();
default: m_object = new MyClass<double>();
}
}
~WrapperClass2()
{
delete m_object;
}
private:
MyClass * m_object;
};
Another idea may be to have some parent AbstractType that I would be using in the vector, but I'm not sure how that would help with the templated type problem.
Different instantiations of a class template are completely unrelated types, so you cannot have a container that directly stores them.
You have a few options:
Keep a collection of pointers to some base class that your class template inherits from:
class Base
{
virtual ~Base {}
virtual void someMethod() const = 0;
};
template <typename T>
class MyClass : public Base
{
void someMethod() const
{
// stuff
}
};
int main()
{
std::vector<std::unique_ptr<Base>> objs;
objs.push_back(std::make_unique<MyClass<int>>());
objs.push_back(std::make_unique<MyClass<std::string>>());
for (auto& i : objs) {
i->someMethod();
}
}
This is a fairly simple approach, but it incurs a bit of runtime overhead with dynamic allocation and RTTI. Note also that someMethod can't return T, since it's a method on a parent class that doesn't know what T is.
Use some sort of type-erased wrapper like boost::any (or the forthcoming std::any in C++17).
#include <any>
#include <string>
#include <vector>
template <typename T>
class MyClass {
public:
T someMethod() const {
// stuff
return {};
}
};
void someFunctionThatTakesInt(int i) {}
void someFunctionThatTakesString(std::string s) {}
int main() {
std::vector<std::any> objs;
objs.push_back(MyClass<int>());
objs.push_back(MyClass<std::string>());
for (const auto& i : objs) {
if (i.type() == typeid(MyClass<int>)) {
auto& mc = std::any_cast<const MyClass<int>&>(i);
someFunctionThatTakesInt(mc.someMethod());
} else if (i.type() == typeid(MyClass<std::string>)) {
auto& mc = std::any_cast<const MyClass<std::string>&>(i);
someFunctionThatTakesString(mc.someMethod());
}
}
}
This approach means that you can have someMethod return T, but makes it much harder to handle retrieving objects from the vector because you have to figure out what type they are before you can do anything with them (you're essentially rolling your own RTTI).
Don't.
Rethink why you need this in the first place. Maybe another approach could work better. Maybe something with callbacks or visitors. I don't know your objective here, so I can't really say what's appropriate.
Can you do a base class and have all other classes inherit from the base class.
And you can make a list that holds a list of base class elements.
Now this is more of a pseudo example, but I hope this way would solve your problem.
Example:
class Base:
{
}
class whatever:Base
{
}
class whatever2:Base
int main()
{
list<whatever> object1;
list<whatever2> object2;
list<list<Base>> mainObj;
mainObj.push_back(object1);
mainObj.push_back(object2);
}
Now if the problem is to just have different datatypes than abstract datatypes in some container. Can't you have a Singly Link List, and have your Node generic.
Example:
template<typenameT>
struct Node
{
T data;
Node* next;
}
class LinkList
{
//Your code:
}