Daily bit(e) C++. Точка кастомизации с помощью ADL

Добавлено 23 сентября 2023 в 00:06

Daily bit(e) C++ #223, реализация точки кастомизации с использованием ADL и концептов C++20.

Daily bit(e) C++

Одна из возможностей ввести точку кастомизации в библиотеке – через 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.

Теги

C++ / CppC++20Daily bit(e) C++Концепты C++ / C++ conceptsПрограммирование

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.