More C++ Idioms/Function Poisoning

Function poisoning

edit

Intent

edit

Hide or prohibit the usage of certain functions, favoring better alternatives.

Also Known As

edit

Motivation

edit

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
// 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 over f (like putting the deleter in a destructor instead of manual call)
  • 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 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 to f, 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
  • g does not reduce readability or hides intent compared to f, which means:
    • 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

Therefore, if g is a strict replacement of f, one can ban f in a codebase.

Known Uses

edit

Replace a function which cannot be removed (for example if it is part of an external library) with a function with improved functionality.

edit

References

edit