placement new in a (virtual) parent class - c++

I have this CRTP:
template <class T>
struct S {
void clear() { new (this) T; }
};
class SS : public S<SS> {
int i = 5;
};
int main() {
SS s;
s.clear();
}
Is clear() guaranteed to work as expected? Does it even matter if S is virtual or not?
For the matter we can assume all the classes inheriting S won't have anything but primitive or POD types, so no fancy constructors and destructors.
I compiled with gcc and valgrind didn't seem to complain but it feels weird.

To recreate the child type at the right place in memory you'll have to cast the this pointer.
Also, if you do not call the destructor, you have to assert that the type is trivially destructible:
template <class T>
struct S {
void clear() {
static_assert(std::is_base_of_v<S, T>);
static_assert(std::is_trivially_destructible_v<T>);
new (static_cast<T*>(this)) T;
}
};
Valgrind did not warn about anything since the this from the base was the same as the derived class, you did not overwrite any memory past what was allocated.

Beyond the static_cast<T*>(this), I also suggest to call dtor on the object first.
template <class T>
struct S {
void clear() {
auto this_ptr = static_cast<T*>(this)
this_ptr->~T();
new (this_ptr) T();
}
};

Related

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 ....

convert pointer type in assignment

I have a class that has:
private:
uint32_t *data;
and the in one of the functions I'm doing:
void foo() {
data = new uint32_t[size];
}
and that is working fine. Now i wanted to make it a bit more flexible, so i wanted to make foo() a template:
template<typename T>
T foo() {
data = new T[size];
}
and i try to use it:
class.foo<uint64_t>();
But compilation fails saying that:
error: cannot convert 'long long unsigned int*' to 'unsigned int*' in assignment
Is it possible to do something like that? I tried declaring
void *data;
and it compiled, but then I cannot do
sizeof(data[1]);
which is essentially why I need to pass the type.
EDIT:
Thank you for your responses, there are a few thing I'd like to add after looking at your answers.
I'm using raw pointer instead of container because it operates on memory that is used also by external hardware (I'm not running this on PC).
Using this memory is optional for this class, so I don't want to allocate it if its not needed.
I use this class in a few places where I don't need *data at all, so I'd rather avoid making the whole class a template.
Another thought:
Default template type might be a good compromise, is there a way to create a class that I won't have to later use that way:
Class<> my;
but still:
Class my;
and if needed:
Class<type> my;
?
Rather than converting your function to a template, convert your class to a template:
template <class T>
class myclass {
private:
T *data;
public:
myclass(size_t size) : data(new T[size]) {
}
... // Add copy constructor, assignment operator, and a destructor
// to properly manage the pointer. See "rule of three" for more info.
};
This way the type of array element becomes part of the type of your class, letting your member functions work with the data without any additional type casting.
Note that using raw array pointer in the class comes with significant liabilities in terms of memory management. You would be better off with std::vector<T>.
You may consider making your whole class a template, like this:
template <typename T>
class Foo
{
private:
T *data;
public:
Foo(size_t size_):
data{new T[size]}
{
}
~Foo()
{
delete[] data;
}
};
Implementation is here only partial. See this about rule of 3, 5, 0.
Or using managed pointers:
template <typename T>
class Foo
{
private:
std::unique_ptr<T[]> data;
size_t size;
public:
Foo(size_t size_):
data{std::make_unique<T[]>(size_)},
size(size_)
{
}
~Foo()
{
// no need to call delete, unique_ptr will do it
}
};
But once you're here, depending on your use case, alternatives may be preferable, like std::vector:
std::vector<uint64_t> v(size);
// ...
std::cout << v.size() << std::endl;
EDIT:
From the additional information you provided, it looks like the following design may better suit your needs:
class Base
{
public:
virtual void* get_data() {
return nullptr;
}
virtual size_t get_size() {
return 0;
}
};
template<typename T>
class Foo : public Base
{
private:
T* data;
size_t size;
public:
Foo(size_t size_):
data{new T[size_]},
size(size_) {}
~Foo() {
delete[] this->data; // same remark as above about rule of 5
}
virtual void* get_data() overriden {
return this->data;
}
virtual size_t get_size() overriden {
return this->size;
}
};
With the following usage:
std::unique_ptr<Base> my_without_data =
std::make_unique<Base>();
std::unique_ptr<Base> my_with_data =
std::make_unique<Foo<type>>(size);
Note that in the second call, std::make_unique returns a unique_ptr<Foo<type>> with an appropriate deleter calling Foo<type>'s destructor. The deleter will be copied when assigning to my_with_data and call Foo<type>'s destructor even if Base's destructor is not declared virtual.
I chose here a design with virtual methods in Base to access data. Depending on your real use case, other ways may be used.
Convert your whole class to a templated class
template<typename T>
class Container {
public:
Container() :
data(NULL)
{}
~Container() {
if (data) {
delete [] data;
}
}
T* foo(int size) {
if (data) {
delete [] data;
}
data = new T[size];
return data;
}
private:
T *data;
};

Is this proper usage of a unique_ptr?

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() {}
};

C++ templating syntax - allocate type with pointer

How can I do memory allocation like this:
template <class T>
class A
{
T Generate()
{
return new T(); // Error
}
};
A<B *> a;
B * pI = A.Generate();
Or can you only ever define something as:
A<B> a;
If I understood you correctly you wish to have specialization of A for pointer types. Try something like:
#include <cstdio>
template <class T>
class A
{
public:
T *Generate()
{
printf("A\n");
return new T; // Error
}
};
template <class T>
class A<T*> {
public:
T *Generate() {
printf("Specialization of A\n");
return new T;
}
};
class B {
};
int main() {
A<B *> a;
B * pI = a.Generate();
}
Edit:
To "override" only a part of the functionality:
template <class T>
class Generator
{
public:
T *Generate()
{
printf("Generator\n");
return new T; // Error
}
};
template <class T>
class Generator<T*> {
public:
T *Generate() {
printf("Specialization of Generator\n");
return new T;
}
};
template <class T>
class A: public Generator<T>
{
public:
// does some other stuff
};
You have a bunch of issues with your code:
A.Generate() should be a.Generate() as Generate is a member function.
new T() returns T*, so your Generate function should look like:
T* Generate()
{
return new T();
}
This should also be reflected in your usage:
A<B *> a;
B ** pI = a.Generate(); //generator for B* returns B**
new will return a pointer so you need the signature
T* Generate()
{
return new T();
}
This function must also be public if you'd like to call it outside the class.
How can I do memory allocation like this
By fixing the syntax and semantic errors.
Return type of Generate is T, yet you return T*. You probably want to change the return type to T*. Accordingly, you must assign the returned type to a T* variable. Since your T is B*, that variable must have the type B**.
You try to call a non-static member of A without an instance. Call the member using the instance instead. Also, that member is private. Make it public.
When you've fixed the code, you'll see that it does memory allocation successfully.
Or can you only ever define something as:
A<B> a;
No, there are many more ways to define something.