Date: Thu, 17 Sep 2020 13:56:28 +0430
I have been tossing this idea in my mind for almost 20 years. The current
schema of overloading operator new belongs to dinosaur era IMO.
If we could provide operator new with the requested type - instead of just
its size (and optionally alignment), then the return type could also be a
custom allocator (rather just void*). This in turn would enable the new
expression to return a smart pointer - rather than a dangerous raw pointer:
smart_allocator operator new(compiler_provided_params,user_provided_params)
value_type { /*...*/};
The corresponding new expression:
auto ptr=new(user_provided_args) value_type {initializer_args};
Would then generate pseudo code sequence like this:
auto ptr = [&}(){
smart_allocator temp_alloc{ operator
new(compiler_provided_args,user_provided_args) value_type };
smart_pointer ret=temp_alloc(initializer_args);
return std::move(ret);
}();
The exact type and number of compiler provided parameters is open to
discussion, but it must at least provide the following functionality:
auto constructor_lambda(compiler_provided_params){
return [](void * void_this, auto && ... initializer){
::new(__none_overloadable_placement__ , void_this) value_type
{std::forward<decltype(initializer)>(initializer) ... };
};
};
the multi-lambda in the above pseudo snippet shall correspond to all
accessible overloads of constructors of value_type in the context of
calling new-expression. other functionality such as destructor
accessibility and assignment operator overload set may also be considered,
but avialablity of accessible constructors is of prime essence IMHO.
This proposition is aiming at encouraging the *usage of raw pointers as
observer-only* idiom. I am trying to combine the syntax clarity of *new* with
safety of *make_smart *family of convenience functions. Other benefits
include:
- passing the whole type - instead of just its size - to the *operator
new* enables safely conveying meta-data about exact type of object to
runtime such as *clonabilty *true destructor. One problem with
traditional *new-expression* is destructor slicing of none-polymorphic
hierarcies (that this proposition can help avoid):
std::unique_ptr<base> { new derived };// dtor is sliced if base does not
declare it as virtual
smarter_unique_ptr<base> { new(smart_tag) derived }; // can avoid
destructor slicing if uses smart overloading for new
- Custom return type of *new *enables optimizing data structure of smart
pointers; e.g it is possible to embed the count of references into the same
block of allocation as the actual object, enabling superfast reference
counting.
- Prohibit lots of issues (double-delete, dangling ptr, memory leak ...)
resulting from improper pointer initialization.
Regards,
FM.
schema of overloading operator new belongs to dinosaur era IMO.
If we could provide operator new with the requested type - instead of just
its size (and optionally alignment), then the return type could also be a
custom allocator (rather just void*). This in turn would enable the new
expression to return a smart pointer - rather than a dangerous raw pointer:
smart_allocator operator new(compiler_provided_params,user_provided_params)
value_type { /*...*/};
The corresponding new expression:
auto ptr=new(user_provided_args) value_type {initializer_args};
Would then generate pseudo code sequence like this:
auto ptr = [&}(){
smart_allocator temp_alloc{ operator
new(compiler_provided_args,user_provided_args) value_type };
smart_pointer ret=temp_alloc(initializer_args);
return std::move(ret);
}();
The exact type and number of compiler provided parameters is open to
discussion, but it must at least provide the following functionality:
auto constructor_lambda(compiler_provided_params){
return [](void * void_this, auto && ... initializer){
::new(__none_overloadable_placement__ , void_this) value_type
{std::forward<decltype(initializer)>(initializer) ... };
};
};
the multi-lambda in the above pseudo snippet shall correspond to all
accessible overloads of constructors of value_type in the context of
calling new-expression. other functionality such as destructor
accessibility and assignment operator overload set may also be considered,
but avialablity of accessible constructors is of prime essence IMHO.
This proposition is aiming at encouraging the *usage of raw pointers as
observer-only* idiom. I am trying to combine the syntax clarity of *new* with
safety of *make_smart *family of convenience functions. Other benefits
include:
- passing the whole type - instead of just its size - to the *operator
new* enables safely conveying meta-data about exact type of object to
runtime such as *clonabilty *true destructor. One problem with
traditional *new-expression* is destructor slicing of none-polymorphic
hierarcies (that this proposition can help avoid):
std::unique_ptr<base> { new derived };// dtor is sliced if base does not
declare it as virtual
smarter_unique_ptr<base> { new(smart_tag) derived }; // can avoid
destructor slicing if uses smart overloading for new
- Custom return type of *new *enables optimizing data structure of smart
pointers; e.g it is possible to embed the count of references into the same
block of allocation as the actual object, enabling superfast reference
counting.
- Prohibit lots of issues (double-delete, dangling ptr, memory leak ...)
resulting from improper pointer initialization.
Regards,
FM.
Received on 2020-09-17 04:27:09