ideas icon indicating copy to clipboard operation
ideas copied to clipboard

Добавить в стандартную библиотеку тип Proxy<T>

Open Makcal opened this issue 9 months ago • 6 comments

Вдохновлено одноимённым типом из языка Haskell.

Реализация

template <typename>
struct Proxy {};

Описание

Proxy<T> это пустой вспомогательный тип, который используется для передачи информации на уровне типов, в основном для type deduction.

Пример

#include <iostream>
#include <tuple>
#include <utility>

template <class>
struct Proxy {};

// Задача фабрики - некоторым образом оборачивать функции для разных наборов аргументов. 
// Например, подводить их все под общую сигнатуру, анализирую сигнатуры F
template <typename Event>
struct CallbackFactory {
    using EventArgs = Event::Args;

    template <typename F>
    static auto create(F&& f) {
        return [&f]<typename... Args>(Proxy<std::tuple<Args...>>) { // a type pattern
            return [f = std::forward<F>(f)](const Args&... args, bool extraArg) {
                return f(args..., extraArg);
            };
        }(Proxy<EventArgs>{}); // a type to match
    }
};

struct MyEvent {
    using Args = std::tuple<int, char>;
};

int main() {
    auto cb = CallbackFactory<MyEvent>::create([](int, char, bool) { std::cout << "Callback!\n"; });
    cb(1, 'a', true);
}

Альтернативой было бы использовать паттерн матчинг в специализации шаблона, но это потребовало бы создавать отдельный класс и выносить код в него. Сравните:

#include <iostream>
#include <tuple>
#include <utility>

namespace detail {
template <typename T>
struct Helper {}; // boilerplate, выглядит ровно как Proxy

template <typename... EventArgs>
struct Helper<std::tuple<EventArgs...>> { // a type pattern
    template <typename F>
    static auto create(F&& f) {
        return [f = std::forward<F>(f)](const EventArgs&... args, bool extraArg) {
            return f(args..., extraArg);
        };
    }
};
} // namespace detail

template <typename Event>
struct CallbackFactory {
    using EventArgs = Event::Args; // a type to match

    template <typename F>
    static auto create(F&& f) {
        return detail::Helper<EventArgs>::create(std::forward<F>(f));
    }
};

struct MyEvent {
    using Args = std::tuple<int, char>;
};

int main() {
    auto cb = CallbackFactory<MyEvent>::create([](int, char, bool) { std::cout << "Callback!\n"; });
    cb(1, 'a', true);
}

Makcal avatar Apr 08 '25 06:04 Makcal