Search code examples
c++c++20terminologystd

What is the clear definition of customization point?


I am learning about C++20 ranges and came across this term "customization point object". I learned and understand that it is a const semiregular function object used for solving customization dispatch from Barry's C++ blog about Niebloids and Customization Point Objects and What are customization point objects and how to use them?.

With this understanding, I thought "customization point" as "the generic code that is customizable by user". For example, function template std::swap is a "customization point" since we as user can write customized function overloads with specific types.

But today when I read C++ standard library design guidelines, I found this:

Make it clear what the customization points are.

Then I doubted my understanding about "customization point" might be wrong, since if customization point is just "generic code like templates", then why do we need to "make it clear" since the definition of template is already clear? Is the meaning of "customization point" something else?

I also found how Eric Niebler defines customization point in Eric Niebler's blog: Customization Point Design in C++11 and Beyond:

hooks used by generic code that end-users can specialize to customize the behavior for their types.

I am not a native English speaker and I am not sure I understand this definition, here is my two guesses:

  1. for function template std::swap, the customization point is not std::swap itself, it is the template parameters (which in this case, type), it is the thing that we specialize to create a customization version from the standard version.
  2. customization point is just the customization version from the standard version, like if we define swap(MyType t1, MyType t2), then this customized definition is the customization point.

Do I get the right understanding with either of these two? What is the clear definition of "customization point"? And why "customization point object", as a function object used to circumvent ADL, is called "customization point object"?


Solution

  • And why "customization point object", as a function object used to circumvent ADL, is called "customization point object"?

    I'll answer your second question first. The term is meant to be literal: it is a thing which is specifically an "object" (note: functions are not objects) which implements a "customization point".

    What is the clear definition of "customization point"?

    Within the context of C++ templates, the term is usually used to refer to a callable thing (function or function-like object, depending on the implementation) that one or more templates will invoke, and that particular callable thing can have its behavior customized when applied to user-provided types without modifying the template that invokes the customization point.

    Consider std::sort. Sorting operations (usually) need to be able to swap objects in a sequence. That is performed (pre-C++20) by having std::sort invoke swap(a, b) (with an assist from the using std::swap; statement). The customization point in this case is swap, and it is being invoked by sort.

    If your type is in a namespace and you have a swap function in that same namespace, it will use ADL to access your swap function in your type's namespace. That's how you customize this particular "customization point".

    However, many types can perform swap operations via copying or moving. So any type that is copyable or moveable is conceptually swappable. Therefore, if the behavior is not customized, default behavior can be used. This default is implemented by std::swap (which also implements the swapping behavior for types that aren't in any namespace).

    So a "customization point" consists of 3 things:

    1. The mechanism of invoking it in a way the user can customize.
    2. Optional default behavior if it is not customized.
    3. The mechanism of defining your customization of it.

    The above ADL-based mechanism is one way to implement a customization point. C++20's customization point objects are another (better) way of defining these. The invocation mechanism is just call the functor using its full-qualified name. The default behavior is defined by the operator() of that functor. And the customization mechanism is defined by various overloads or if constexpr constructs within the functor.