Function poisoning
Intent
Hide or prohibit the usage of certain functions, favoring better alternatives.
Also Known As
Motivation
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 myself and other people that are working on the same project), all (or just many) functions that allocate memory and return a raw pointer, and replace them with something more RAII-friendly.
Solution and Sample Code
// header of external library
foo* create_foo();
foo_destroy(foo*);
// our header, wiht 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 over f. g can act as a drop-in replacement for f, 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 to g in the working codebase is a trivial operation. the cost of removing f is not too high. g does not have any drawback compared to f, in particular 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 g does not reduce readability or hides intent compared to f there is no need to document what g does since it should do the same of f, only the benefits if those are not clear to everyone
And therefore, if g is a strict replacement of f, we can apply the banning policy on f in our codebase.
Known Uses
Replace a function which cannot be removed (for example if it is part of an external library) with a function with improved functionality.