constexpr версия :: std :: function - PullRequest
       57

constexpr версия :: std :: function

0 голосов
/ 30 декабря 2018

Я нахожусь в поиске функции :: std ::, пригодной для использования в constexpr.Случай использования: у меня есть функция, которая принимает указатель на функцию в качестве аргумента, и вторая, которая передает лямбда-функцию первой функции.Оба полностью исполняются во время компиляции, поэтому я хочу их объединить.Например:

template <class _Type>
class ConstexprFunctionPtr
{
    private:
        using Type = typename ::std::decay<_Type>::type;
        const Type function;

    public:
        constexpr inline
        ConstexprFunctionPtr(const Type f)
        : function(f)
        { }

        template <typename... Types>
        constexpr inline
        auto
        operator() (Types... args)
        const {
            return function(args... );
        }
};

constexpr inline
void
test()
{
    ConstexprFunctionPtr<int(int)> test([](int i) -> int {
        return i + 1;
    });
    int i = test(100);

    ConstexprFunctionPtr<int(int)> test2([=](int i) -> int {
        return i + 1;
    });
    i = test2(1000);
}

Однако это работает только потому, что я преобразовываю лямбду в указатель функции, и, конечно, не удается захватить лямбда-выражения, как показано во втором примере.Кто-нибудь может дать мне несколько советов о том, как сделать это с захватом лямбд?

Это продемонстрировало бы случай использования:

constexpr
void
walkOverObjects(ObjectList d, ConstexprFunctionPtr<void(Object)> fun) {
// for i in d, execute fun
}

constexpr
void
searchObjectX(ObjectList d) {
walkOverObjects(d, /*lambda that searches X*/);
}

Спасибо, Джек

1 Ответ

0 голосов
/ 30 декабря 2018

Я нахожусь в поиске функции :: std ::, пригодной для использования в constexpr

Остановитесь прямо здесь.это невозможно.std::function - это полиморфная функция-обертка.Лямбды без сохранения состояния, лямбды с полным состоянием, функторы, указатели функций, ссылки на функции - все они могут создать действительный std::function, который может изменяться во время выполнения.поэтому создание эквивалента времени компиляции - просто трата времени.

Если вам нужен просто параметр универсальной функции времени компиляции, вы можете просто использовать шаблоны

template<class functor_type>
class my_generic_function_consumer_class{

   using decayed_function_type = typename std::decay_t<functor_type>;

   decayed_function_type m_functor;

};

В своем коде просто примите универсальный функтор и подтвердите его с помощью static_assert:

template<class function_type>
constexpr void walkOverObjects(ObjectList d, function_type&& fun) {
    static_assert(std::is_constructible_v<std::function<void(ObjectList), function_type>>,
                  "function_type given to walkOverObjects is invalid.");
}
...