Helpers - компьютеры, интернет, программирование

Как извлечь тип возвращаемого значения лямбды и пакет переменных параметров обратно из общего шаблона ‹typename T›

Я хочу создать шаблонный класс или функцию, которая получает лямбду и помещает ее внутри std :: function ‹> Лямбда может иметь любое количество входных параметров [] (int a, float b, ...) std :: функция ‹> должна соответствовать типу лямбда-оператора ()

template <typename T> 
void getLambda(T t) {
   // typedef lambda_traits::ret_type RetType; ??
   // typedef lambda_traits::param_tuple --> somehow back to parameter pack Args...
   std::function<RetType(Args...)> fun(t);
}

int main() {
    int x = 0;
    getLambda([&x](int a, float b, Person c){}); 
}

Поэтому мне нужно как-то извлечь тип возвращаемого значения и пакет параметров.

Ответ здесь предлагает использовать частичную спецификацию лямбда-оператора :: ()

template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
    enum { arity = sizeof...(Args) };
    // arity is the number of arguments.

    typedef ReturnType result_type;

    template <size_t i>
    struct arg
    {
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
        // the i-th argument is equivalent to the i-th tuple element of a tuple
        // composed of those arguments.
    };
};

Но мне нужен способ преобразовать кортеж ‹> обратно в пакет параметров, чтобы создать правильный экземпляр std :: function‹>


  • Что такое лямбда общего назначения? [](auto... args){}? 22.04.2017

Ответы:


1
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
    using result_type = ReturnType;
    using arg_tuple = std::tuple<Args...>;
    static constexpr auto arity = sizeof...(Args);
};

template <class F, std::size_t ... Is, class T>
auto lambda_to_func_impl(F f, std::index_sequence<Is...>, T) {
    return std::function<typename T::result_type(std::tuple_element_t<Is, typename T::arg_tuple>...)>(f);
}

template <class F>
auto lambda_to_func(F f) {
    using traits = function_traits<F>;
    return lambda_to_func_impl(f, std::make_index_sequence<traits::arity>{}, traits{});
}

Приведенный выше код должен делать то, что вы хотите. Основная идея, как видите, - создать целочисленный пакет. Это не шаблонный эквивалент вариативных чисел. Я не знаю какой-либо техники, с помощью которой можно было бы использовать такой пакет без вызова другой функции, поэтому обычно в таких ситуациях с кортежами вы увидите вложенную функцию «impl», которая выполняет всю работу. Когда у вас есть целочисленный пакет, вы расширяете его при доступе к кортежу (также работает для получения значений).

О стилистике: используйте using, а не typename, особенно в тяжелом коде шаблонов, поскольку первый также может использовать псевдонимы для шаблонов. И не используйте этот enum трюк для хранения статического значения без использования пробела; компиляторы все равно оптимизируют это, и использование целого числа static constexpr намного яснее.

22.04.2017
  • Ага, так близко, я попытался скомпилировать это, есть кое-что, что мне не хватает в паренах и расширении ... если добрая душа может предложить исправление, я исправлю это, иначе, возможно, мне следует удалить и позволить кому-то еще ответ. В любом случае, использование index_sequence - важная идея. 22.04.2017
  • Да, это не компилируется 22.04.2017
  • @barney Хорошо, я понял, не нужны были лишние пары, исправляю. 22.04.2017
  • И я считаю, что это должно быть return std :: function ‹typename T :: result_type (std :: tuple_element_t‹ Is, typename T :: arg_tuple ›...)› (f); 22.04.2017
  • @barney Да, я тоже исправил. Спасибо, рад, что помог! Ваше здоровье. 22.04.2017
  • кстати, как сделать его совместимым с C ++ 11 с конечным типом возврата (поскольку auto там не работает) 22.04.2017
  • @barney По сути, вы просто используете конечный возвращаемый тип, где вы вызываете decltype в возвращаемом выражении. Это уродливо, однообразно и бессмысленно ... но таков TMP в C ++ 11 :-). 22.04.2017
  • Но std::index_sequence недоступен в C ++ 11 :( 02.06.2017
  • @Chnossos Вы можете легко написать это сами, просто погуглите. 02.06.2017
  • Новые материалы

    Интуитивное понимание тензоров в машинном обучении
    Тензор является важной концепцией во многих научных областях, таких как математика, физика, обработка сигналов и компьютерное зрение, и это лишь некоторые из них. В математике тензор — это..

    Использование машинного обучения для диагностики болезни Альцгеймера, часть 4
    Маркеры семантической согласованности для ранней диагностики болезни Альцгеймера (arXiv) Автор: Давиде Колла , Маттео Дельсанто , Марко Агосто , Бенедетто Витиелло , Даниэле Паоло Радичони..

    Почему объяснимость так важна прямо сейчас?
    По мере того, как системы искусственного интеллекта и инструменты на основе машинного обучения распространяются в нашей повседневной жизни, как практики, так и критики все чаще заявляют о..

    Анимированный математический анализ
    Использование Manim для создания математических анимированных визуализаций Визуализация данных помогает понять скрытые закономерности в данных, которые невозможно визуализировать..

    Создание простого слайдера изображений с помощью JavaScript
    Узнайте, как создать базовый слайдер изображений с помощью HTML, CSS и JavaScript. Введение В этом уроке мы создадим удобный слайдер изображений, используя JavaScript, HTML и CSS. Ползунок..

    Создание базы данных с помощью супергероя «Python»
    В этом посте мы узнаем, как создать «базу данных SQLite с помощью модуля python sqlite3, создав простую функцию входа и регистрации. Готовы ли вы к этому путешествию? Если да , давайте приступим..

    ИИ для чайников: руководство для начинающих по пониманию будущего технологий
    Вы чувствуете, что остались позади в мире ИИ? Не волнуйтесь, вы не одиноки! Со всей этой шумихой вокруг искусственного интеллекта может быть трудно понять, с чего начать. Но не позволяйте сленгу..