Daily bit(e) C++. Точка кастомизации с помощью ADL
Daily bit(e) C++ #223, реализация точки кастомизации с использованием ADL и концептов C++20.
Одна из возможностей ввести точку кастомизации в библиотеке – через ADL (Argument Dependent Lookup – поиск, зависящий от аргументов). С появлением концептов C++20 этот подход стал намного понятнее.
Ниблоид (nebloid) в сочетании с концептом, который обнаруживает наличие пользовательской реализации, может обрабатывать возврат к реализации по умолчанию без необходимости возиться с пространствами имен на вызывающей стороне.
#include <utility>
namespace dflt {
namespace impl {
// Концепт, проверяющий правильность ADL вызова.
template <typename T>
concept HasADL = requires(T a) { do_something(a); };
// Основной механизм выбора между реализацией
// по умолчанию или реализацией ADL.
struct DoSomethingFn
{
// Тип имеет собственную реализацию,
// просто вызывает, полагаясь на ADL.
template <typename T> void operator()(T&& arg) const
requires HasADL<T> { do_something(std::forward<T>(arg)); }
// Тип не имеет собственной реализации,
// использует значение по умолчанию.
template <typename T> void operator()(T&&) const
requires (!HasADL<T>) { /* default implementation */ }
};
}
// inline пространство имен позволяет inline переменной
// не конфликтовать с реализациями типов в пространстве имен dflt.
inline namespace var {
// Вызывается только как dflt::do_something, невидимый для ADL.
constexpr inline auto do_something = impl::DoSomethingFn{};
}
}
namespace lib { struct X { friend void do_something(const X&){}; }; }
namespace dflt { struct Y { friend void do_something(const Y&){}; }; }
int main()
{
int a = 0; lib::X x; dflt::Y y;
// Нет явной реализации для int, возвращается к значению по умолчанию.
dflt::do_something(a);
// Вызывает дружественную функцию do_something для X
dflt::do_something(x);
// Вызывает дружественную функцию do_something для Y
dflt::do_something(y);
// Вызовы чисто-ADL, которые вызывают пользовательские реализации.
do_something(x);
do_something(y);
}
Открыть пример на Compiler Explorer.