Date: Fri, 4 Sep 2026 06:54:56 +0200
I know that problem from Qt; it works in the same way as wxWidgets. Wt (webtoolkit.eu) used to work in the same way as Qt, but they have made the switch to modern C++ and are now using std::unique_ptr (I believe together with a templated factory function). So, there are (backwards incompatible) solutions a library can use.
I would claim that this feature would be useful. However, it does not follow the zero cost abstraction principle. You need to store the information somewhere and for 99% of the variables you don‘t need it. It is a total waste of space. So, even if it is useful, we shouldn‘t standardize it.
> On Sep 3, 2026, at 5:54 PM, Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> Some libraries have classes that you must create objects of with
> 'new', because later they're destroyed by an object management system
> which uses 'delete'.
>
> An example of this is wxWindow in the wxWidgets library. You can do this:
>
> auto *p = new wxButton();
> main_window.AddWidget( p );
>
> but you can't do this:
>
> wxButton b;
> main_window.AddWidget( &b );
>
> The problem with the latter is that it will later call 'delete' on a
> variable that wasn't new'd.
>
> So I was thinking, would it be helpful if C++29 had the following?
>
> class wxWindow {
> public:
> wxWindow(void)
> {
> assert( std::came_from_new(this) );
> }
> };
>
> Or perhaps even a more generic function like "std::origin" which would return:
>
> 1 - static global
> 2 - static thread-local
> 3 - stack
> 4 - heap
>
> On Linux I think this would be coded something along the lines of:
>
> bool came_from_heap(const void *p)
> {
> if (p == nullptr)
> {
> return false;
> }
>
> const std::uintptr_t address = reinterpret_cast<std::uintptr_t>(p);
>
> FILE *file = std::fopen("/proc/self/maps", "r");
>
> if (file == nullptr) return false;
>
> char line[512];
>
> while (std::fgets(line, sizeof(line), file) != nullptr)
> {
> std::uintptr_t begin;
> std::uintptr_t end;
> char permissions[5];
> char pathname[256];
>
> const int fields = std::sscanf(
> line,
> "%lx-%lx %4s %*s %*s %*s %255[^\n]",
> &begin,
> &end,
> permissions,
> pathname);
>
> if (fields == 4 &&
> address >= begin &&
> address < end &&
> std::strcmp(pathname, "[heap]") == 0)
> {
> std::fclose(file);
> return true;
> }
> }
>
> std::fclose(file);
>
> return false;
> }
>
> An alternative to this would be to force a compile-time error if you
> don't use new to create an object:
>
> class wxWindow {
> public:
> [[must_be_new]] wxWindow(void)
> {
> // code goes here
> }
> };
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
I would claim that this feature would be useful. However, it does not follow the zero cost abstraction principle. You need to store the information somewhere and for 99% of the variables you don‘t need it. It is a total waste of space. So, even if it is useful, we shouldn‘t standardize it.
> On Sep 3, 2026, at 5:54 PM, Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> Some libraries have classes that you must create objects of with
> 'new', because later they're destroyed by an object management system
> which uses 'delete'.
>
> An example of this is wxWindow in the wxWidgets library. You can do this:
>
> auto *p = new wxButton();
> main_window.AddWidget( p );
>
> but you can't do this:
>
> wxButton b;
> main_window.AddWidget( &b );
>
> The problem with the latter is that it will later call 'delete' on a
> variable that wasn't new'd.
>
> So I was thinking, would it be helpful if C++29 had the following?
>
> class wxWindow {
> public:
> wxWindow(void)
> {
> assert( std::came_from_new(this) );
> }
> };
>
> Or perhaps even a more generic function like "std::origin" which would return:
>
> 1 - static global
> 2 - static thread-local
> 3 - stack
> 4 - heap
>
> On Linux I think this would be coded something along the lines of:
>
> bool came_from_heap(const void *p)
> {
> if (p == nullptr)
> {
> return false;
> }
>
> const std::uintptr_t address = reinterpret_cast<std::uintptr_t>(p);
>
> FILE *file = std::fopen("/proc/self/maps", "r");
>
> if (file == nullptr) return false;
>
> char line[512];
>
> while (std::fgets(line, sizeof(line), file) != nullptr)
> {
> std::uintptr_t begin;
> std::uintptr_t end;
> char permissions[5];
> char pathname[256];
>
> const int fields = std::sscanf(
> line,
> "%lx-%lx %4s %*s %*s %*s %255[^\n]",
> &begin,
> &end,
> permissions,
> pathname);
>
> if (fields == 4 &&
> address >= begin &&
> address < end &&
> std::strcmp(pathname, "[heap]") == 0)
> {
> std::fclose(file);
> return true;
> }
> }
>
> std::fclose(file);
>
> return false;
> }
>
> An alternative to this would be to force a compile-time error if you
> don't use new to create an object:
>
> class wxWindow {
> public:
> [[must_be_new]] wxWindow(void)
> {
> // code goes here
> }
> };
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2026-09-04 04:55:15
