Reputation: 2235
I would like to have a member function unique-ptr with a static deleter function where the function is known at compiletime and no function pointer is required at allocation. I do not know if it is possible but this test confuses me:
#include <memory>
#include <string>
#include <iostream>
struct Apa {
std::string name;
~Apa() {
std::cout << name << " deleted\n";
}
};
static void staticDeleter(Apa *a) {
std::cout << "static deleter\n";
delete a;
}
int main() {
auto deleter = [] (Apa *a) {
std::cout << "deleter\n";
delete a;
};
{
// This is what I want but as a member of a struct
auto ptr1 = std::unique_ptr<Apa, decltype(deleter)>{new Apa{"Apan"}}; // <----------------
std::cout << sizeof(ptr1) << " -> Apan\n";
}
{
auto ptr2 = std::unique_ptr<Apa, decltype(&staticDeleter)>(new Apa{"Beata"}, staticDeleter);
// When trying to omit this argument this line does not compile ------------^
std::cout << sizeof(ptr2) << " -> Beta\n";
}
}
This results in the output
8 -> Apan
deleter
Apan deleted
16 -> Beta
static deleter
Beata deleted
So unless there is some unknown compiler magic, the size of the pointers indicate that it is in fact possible to create a unique ptr with static deleter function.
When trying to do the same thing inside a struct
#include <memory>
#include <iostream>
struct Apa{
};
struct Container {
using deleter = decltype((Apa*) {}); // Edit: This was a typo: se below
std::unique_ptr<Apa, deleter> ptr ;
};
int main() {
std::cout << sizeof(Container::ptr) << "\n";
}
The output 16
shows that the unique_ptr does want a pointer to the deleter function.
Is there any way to make this work so that I define a unique_ptr with a custom deleter function inside a class that is statically defined instead of specified at runtime?
After some feedback from @eerorika i realized that the code actually works if the lambda is written correctly. Working code:
#include <memory>
#include <iostream>
struct Apa{
~Apa() {
std::cout << "Apa deleted\n";
}
};
struct Container {
using deleter = decltype([](Apa* apa) {
std::cout << "deleter\n";
delete apa;
});
std::unique_ptr<Apa, deleter> ptr = std::unique_ptr<Apa, deleter>{new Apa} ;
};
int main() {
std::cout << sizeof(Container::ptr) << "\n";
Container container{};
}
Yields output:
8
deleter
Apa deleted
Upvotes: 3
Views: 970
Reputation: 238411
using deleter = decltype((Apa*) {});
This is an unnecessarily convoluted way of writing:
using deleter = Apa*;
The type Apa*
doesn't satisfy the requirement that std::unique_ptr
imposes on its deleter because Apa*
isn't a FunctionObject. The example program is ill-formed (at least if you try to create an instance of it). Hence, it doesn't matter what size the object is.
Is there any way to make this work so that I define a unique_ptr with a custom deleter function inside a class that is statically defined instead of specified at runtime?
Your lambda example works since C++20. You can define similar deleter as a class, which works with earlier versions as well. For example:
struct deleter {
void operator()(Apa* ptr) {
std::cout << "custom deleter\n";
delete ptr;
}
};
struct Container {
std::unique_ptr<Apa, deleter> ptr ;
};
Upvotes: 3