Вывод типа при передаче лямбды в переменную std :: function

Найдите папку, в которой находится django-admin.py. Затем перейдите в Панель управления> Система> Дополнительные параметры системы> Переменные среды. В пользовательских переменных и / или системных переменных выполните поиск записи с именем PATH. Измените его, добавив папку, которую вы обнаружили ранее, используйте другие записи в качестве руководства, в основном просто убедитесь, что они разделены ;. Если вы сделали все эти шаги, но все еще находитесь в том же приглашении cmd, которое вы использовали, прежде чем делать это, закройте его и откройте новый, чтобы он набирал ваши изменения.

4
задан Alan Birtles 17 January 2019 в 08:24
поделиться

3 ответа

Вы можете использовать трюк с руководством по выводу std::function, чтобы вытащить аргументы, но вы действительно не хотите, чтобы действительно создавало a std::function. Вы хотите сложить в лямбда-стране. std::function добавляет накладные расходы и распределение из-за стирания типа - но вы ничего не делаете, так как на самом деле требуются преимущества, которые обеспечивает стирание типа. Это все потеря и нет победы. На самом деле не делайте std::function .

Тем не менее, вам все еще, конечно, нужны аргументы. Таким образом, вы можете сделать это:

template <typename T> struct type { };

template <typename F>
void get(size_t index, F f) {
    using function_type = decltype(std::function(f));
    get_impl(index, f, type<function_type>{});
}

По сути, мы берем некоторые вызываемые - и затем мы выводим std::function из него. Это дает нам некоторый тип. В конкретном примере в OP этот тип std::function<void(comp_a&, comp_b&)>. Затем мы просто перенаправляем этот тип в другую функцию - как пустой объект. Нет накладных расходов. Повторим, мы на самом деле не создаем std::function - мы просто передаем его тип.

Эта другая функция может использовать преимущество знания того, что знает std::function:

template <typename T> using uncvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

template <typename F, typename R, typename... Args>
void get_impl(size_t index, F f, type_t<std::function<R(Args...)>>) {
    f(std::get<uncvref_t<Args>::id>(components)[index] ...);
}

Вам нужно uncvref_t, чтобы обработать случай, когда Args может или не может быть ссылкой или [ 1114] резюме -qualified.

Теперь, это не будет работать для любого вызываемого. Если вы передадите общую лямбду, вывод std::function не удастся. Но тогда ... это не могло сработать, так что это не большая потеря?

0
ответ дан Barry 17 January 2019 в 08:24
поделиться

Я не уверен, для чего предназначена структура identity, но удаление ее дает более четкое сообщение об ошибке (сбой вывода шаблона).

Компилятор не может получить тип std::function из лямбды. Чтобы доказать это, компилируется следующее:

storage.get(2, std::function<void(comp_a& a, comp_c& c)>([](comp_a& a, comp_c& c) {              // Doesn't work
    std::cout << a.val << " " << c.val << std::endl;
}));

Итак, чтобы заставить его работать, нам просто нужно помочь компилятору в получении типов. Заимствуя у http://www.cplusplus.com/forum/general/223816/ следующие работы:

namespace detail
{
    template < typename T > struct deduce_type;

    template < typename RETURN_TYPE, typename CLASS_TYPE, typename... ARGS >
    struct deduce_type< RETURN_TYPE(CLASS_TYPE::*)(ARGS...) const >
    {
        using type = std::function< RETURN_TYPE(ARGS...) >;
    };
}

template<size_t size, typename ... Cs>
struct storage
{
    template<typename ... Ts>
    void get(size_t index, typename std::function<void(Ts& ...)> f)
    {
        f(std::get<Ts::id>(components)[index] ...);
    }

    template<typename Lambda>
    void get(size_t index, Lambda l)
    {
        get( index, typename detail::deduce_type< decltype( &Lambda::operator() ) >::type( l ) );
    }

    std::tuple<std::array<Cs, size> ...> components;
};
0
ответ дан Alan Birtles 17 January 2019 в 08:24
поделиться

Вы пометили C ++ 17, так что вы можете использовать std::function руководства по дедукции

Итак, как предлагает Алан Биртлз, вы можете получить лямбду как простой тип, преобразовав ее в std::function (инструкции по выводу) и вывод типа аргументов.

Что-то как

template<size_t size, typename ... Cs>
struct storage
{    
    template<typename ... Ts>
    void get(size_t index, std::function<void(Ts& ...)> f)
    { f(std::get<Ts::id>(components)[index] ...); }

    template <typename F>
    void get(size_t index, F f)
    { get(index, std::function{f}); }

    std::tuple<std::array<Cs, size> ...> components;
};
0
ответ дан max66 17 January 2019 в 08:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: