ideas
ideas copied to clipboard
Добавить в стандартную библиотеку тип Proxy<T>
Вдохновлено одноимённым типом из языка 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);
}