More C++ Idioms/Function Poisoning

From Wikibooks, open books for an open world
Jump to navigation Jump to search

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 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 | 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.

[edit | edit source]

References

[edit | edit source]