More C++ Idioms/Function Poisoning
Function poisoning
[edit | edit source]Intent
[edit | edit source]Hide or prohibit the usage of certain functions, favoring better alternatives.
Also Known As
[edit | edit source]Motivation
[edit | edit source]Often, when interacting with libraries that have a C or pre-C++11 interface, since modern C++ is more expressive, it would be very convenient to hide (from people that are working on a project), all (or just many) functions that allocate memory and return a raw pointer (like a T*
), and replace them with something more RAII-friendly (like a unique_ptr
).
Solution and Sample Code
[edit | edit source]// header of external library
foo* create_foo();
foo_destroy(foo*);
// our header, with our enhanced version
struct foo_deleter {
void operator()(foo* h) {
// foo_destroy provided by the 3rd party library as function, macro, ...
foo_destroy(h);
}
};
using unique_foo = std::unique_ptr<foo, foo_deleter>;
inline unique_foo create_unique_foo() {
// we do not have poisoned create_foo yet!
return unique_foo{create_foo()};
}
#pragma GCC poison create_foo
// from now on, no-one can use create_foo again!
// at least with GCC and clang
Guideline for banning a function:
A function g
is a strict replacement of a function f
of a library L if:
g
provides clear benefits overf
(like putting the deleter in a destructor instead of manual call)g
can act as a drop-in replacement forf
, which means:- it can interact with the library L without writing more than one line of glue code that has no particular drawbacks
- updating
f
tog
in the codebase is a trivial operation (use Change All Occurences or a simple find-and-replace) - the cost of removing
f
is not too high
g
does not have any drawback compared tof
, which means:- it does not add any measurable runtime overhead compared to
f
- it does not add any new dependency
- it cannot be less type-safe, exception-safe or thread-safe
- it cannot introduce new kinds of programming errors
- it does not add any measurable runtime overhead compared to
g
does not reduce readability or hides intent compared tof
, which means:- there is no need to document what
g
does since it should do the same off
, only the benefits if those are not clear to everyone
- there is no need to document what
Therefore, if g
is a strict replacement of f
, one can ban f
in a codebase.
Known Uses
[edit | edit source]Replace a function which cannot be removed (for example if it is part of an external library) with a function with improved functionality.