Сообщение Re: Получить сигнатуру из ламбды от 14.08.2020 7:15
Изменено 14.08.2020 7:19 rg45
Re: Получить сигнатуру из ламбды
Здравствуйте, Barbar1an, Вы писали:
B>если у нас
B>
B>возможно както?
Да в принципе, не сложно, если вспомнить, что все лямбды — это просто объекты классов с перегруженными operator(). Можно даже без концептов и SFINAE. И можно даже предоставить универсальную реализацию, которая будет применима не только к лямбдам, но и к обычным функциям и к определенным пользователем классам функциональным объектам.
Ниже эскизная реализация. До полной реализации здесь не хватает поддержки 'const', 'volatile', '&', '&&', 'nothrow' и всех их комбинаций.
http://coliru.stacked-crooked.com/a/7c29edffdf60891a
B>если у нас
B>
B>template<class L> Subscribe(L lambda)
B>{
B> std::function<сигнатура вызова lambdы> f; // типа void(int, int)
B> std::function<void(сигнатура параметров lambdы)> f; // типа только "int, int"
B>}
B>Subscribe([](int, int){});
B>
B>возможно както?
Да в принципе, не сложно, если вспомнить, что все лямбды — это просто объекты классов с перегруженными operator(). Можно даже без концептов и SFINAE. И можно даже предоставить универсальную реализацию, которая будет применима не только к лямбдам, но и к обычным функциям и к определенным пользователем классам функциональным объектам.
Ниже эскизная реализация. До полной реализации здесь не хватает поддержки 'const', 'volatile', '&', '&&', 'nothrow' и всех их комбинаций.
http://coliru.stacked-crooked.com/a/7c29edffdf60891a
#include <string>
#include <tuple>
#include <type_traits>
template <typename>
struct CallableTraits;
template <typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(ParamT...)>
{
static constexpr size_t Arity = sizeof...(ParamT);
using Signature = ReturnT(ParamT...);
using ReturnType = ReturnT;
using ParameterTypes = std::tuple<ParamT...>;
};
template <typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(*)(ParamT...)> : CallableTraits<ReturnT(ParamT...)> {};
template <typename T, typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(T::*)(ParamT...)> : CallableTraits<ReturnT(ParamT...)> {};
template <typename T, typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(T::*)(ParamT...) const> : CallableTraits<ReturnT(ParamT...)> {};
template <typename T>
struct CallableTraits : CallableTraits<decltype(&std::decay_t<T>::operator())> {};
template <typename T>
constexpr size_t CallableArity = CallableTraits<T>::Arity;
template <typename T>
using CallableSignature = typename CallableTraits<T>::Signature;
template <typename T>
using CallableReturnType = typename CallableTraits<T>::ReturnType;
template <typename T, size_t I>
using CallableParameterType = std::tuple_element_t<I, typename CallableTraits<T>::ParameterTypes>;
int main()
{
int i = 42;
auto lambda = [=](int, double, const std::string&) { return i; };
using L = decltype(lambda);
static_assert(CallableArity<L> == 3, "");
static_assert(std::is_same_v<CallableSignature<L>, int(int, double, const std::string&)>, "");
static_assert(std::is_same_v<CallableParameterType<L, 0>, int>, "");
static_assert(std::is_same_v<CallableParameterType<L, 1>, double>, "");
static_assert(std::is_same_v<CallableParameterType<L, 2>, const std::string&>, "");
static_assert(std::is_same_v<CallableReturnType<L>, int>, "");
}
Re: Получить сигнатуру из ламбды
Здравствуйте, Barbar1an, Вы писали:
B>если у нас
B>
B>возможно както?
Да в принципе, не сложно, если вспомнить, что все лямбды — это просто объекты классов с перегруженными operator(). Можно даже без концептов и SFINAE. И можно даже предоставить универсальную реализацию, которая будет применима не только к лямбдам, но и к обычным функциям и к определенным пользователем классам функциональных объектов.
Ниже эскизная реализация. До полной реализации здесь не хватает поддержки 'const', 'volatile', '&', '&&', 'nothrow' и всех их комбинаций.
http://coliru.stacked-crooked.com/a/7c29edffdf60891a
B>если у нас
B>
B>template<class L> Subscribe(L lambda)
B>{
B> std::function<сигнатура вызова lambdы> f; // типа void(int, int)
B> std::function<void(сигнатура параметров lambdы)> f; // типа только "int, int"
B>}
B>Subscribe([](int, int){});
B>
B>возможно както?
Да в принципе, не сложно, если вспомнить, что все лямбды — это просто объекты классов с перегруженными operator(). Можно даже без концептов и SFINAE. И можно даже предоставить универсальную реализацию, которая будет применима не только к лямбдам, но и к обычным функциям и к определенным пользователем классам функциональных объектов.
Ниже эскизная реализация. До полной реализации здесь не хватает поддержки 'const', 'volatile', '&', '&&', 'nothrow' и всех их комбинаций.
http://coliru.stacked-crooked.com/a/7c29edffdf60891a
#include <string>
#include <tuple>
#include <type_traits>
template <typename>
struct CallableTraits;
template <typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(ParamT...)>
{
static constexpr size_t Arity = sizeof...(ParamT);
using Signature = ReturnT(ParamT...);
using ReturnType = ReturnT;
using ParameterTypes = std::tuple<ParamT...>;
};
template <typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(*)(ParamT...)> : CallableTraits<ReturnT(ParamT...)> {};
template <typename T, typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(T::*)(ParamT...)> : CallableTraits<ReturnT(ParamT...)> {};
template <typename T, typename ReturnT, typename...ParamT>
struct CallableTraits<ReturnT(T::*)(ParamT...) const> : CallableTraits<ReturnT(ParamT...)> {};
template <typename T>
struct CallableTraits : CallableTraits<decltype(&std::decay_t<T>::operator())> {};
template <typename T>
constexpr size_t CallableArity = CallableTraits<T>::Arity;
template <typename T>
using CallableSignature = typename CallableTraits<T>::Signature;
template <typename T>
using CallableReturnType = typename CallableTraits<T>::ReturnType;
template <typename T, size_t I>
using CallableParameterType = std::tuple_element_t<I, typename CallableTraits<T>::ParameterTypes>;
int main()
{
int i = 42;
auto lambda = [=](int, double, const std::string&) { return i; };
using L = decltype(lambda);
static_assert(CallableArity<L> == 3, "");
static_assert(std::is_same_v<CallableSignature<L>, int(int, double, const std::string&)>, "");
static_assert(std::is_same_v<CallableParameterType<L, 0>, int>, "");
static_assert(std::is_same_v<CallableParameterType<L, 1>, double>, "");
static_assert(std::is_same_v<CallableParameterType<L, 2>, const std::string&>, "");
static_assert(std::is_same_v<CallableReturnType<L>, int>, "");
}