Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用lambda初始化包含std::函数的类_C++_Templates_C++11_Lambda_Std Function - Fatal编程技术网

C++ 使用lambda初始化包含std::函数的类

C++ 使用lambda初始化包含std::函数的类,c++,templates,c++11,lambda,std-function,C++,Templates,C++11,Lambda,Std Function,我以以下方式创建了一个包含std::function的模板类作为成员: template<typename Ret, typename... Args> class Foo { private: std::function<Ret(Args...)> _func; public: Foo(const std::function<Ret(Args...)>& func): _func(func) {} }; 但

我以以下方式创建了一个包含
std::function
的模板类作为成员:

template<typename Ret, typename... Args>
class Foo
{
private:
    std::function<Ret(Args...)> _func;

public:
    Foo(const std::function<Ret(Args...)>& func):
        _func(func)
    {}
};
但是,我无法创建以lambda为参数的
make_foo
重载:

template<typename Ret, typename... Args>
auto make_foo(??? func)
    -> Foo<Ret, Args...>
{
    return { std::function<Ret(Args...)>(func) };
}
模板
自动生成函数(?func)
->福
{
返回{std::function(func)};
}

我只是找不到一种方法让返回类型和参数类型自动从lambda推导出来。有一种惯用的方法来解决这样的问题吗?

我有一个例子,它适用于
mutable
lambdas。我不太明白如何获得简历会员资格

首先,这是我们要寻找的函数模板:

#include <functional>

template <typename R, typename ...Args>
void foo(std::function<R(Args...)> f)
{ }
例如:

int q;
bar([&](int a, int b) mutable -> int { q = a + b; return q / b; });

您可以使用普通的,
const
lambdas和这个修改后的特性,尽管我不喜欢把函数类型拼出来:

template <typename C, typename R, typename ...Args>
struct remove_member<R (C::*)(Args...) const>
{ using type = R(Args...); };
模板
结构删除成员
{使用type=R(Args…);};

我认为如果我使用
typename std::remove\u cv::type
,它可能会与原始代码一起工作,但至少在GCC上,这不起作用,因为lambda的操作符类型上设置了一些奇怪的
\uuu属性((const))
,这似乎会干扰模板专门化。

好的,所以我想我会死,但我终于做到了

首先,我使用了常用的索引。由于我没有官方指数,我使用了几个月前写的旧指数:

template<std::size_t...>
struct indices {};

template<std::size_t N, std::size_t... Ind>
struct make_indices:
    make_indices<N-1, N-1, Ind...>
{};

template<std::size_t... Ind>
struct make_indices<0, Ind...>:
    indices<Ind...>
{};
代码有点难看和不可读,但它确实有效。希望它现在不依赖于某些实现定义的行为。另外,谢谢大家的建议,这很有帮助!:)

intmain()
{
自动λ=[](整数i,浮点b,长c)
{
返回长(i*10+b+c);
};
auto foo=make_foo(λ);

std::你能不能用
T
(或者
F
,如果你愿意的话)替换所有东西。也许可以签出。重载将
std::function
作为参数,足以允许lambdas。事实上,您应该将它用作唯一的重载,因为它同时接受lambdas和函数指针。@0x499602D2好吧,但它:/@0x499602D2:不适用于lambdas。有太多用户定义的转换。如果我之前发现了,我将本应该不会那么痛苦…Morwenn在一周内拯救了2次…我碰巧需要这个。它似乎有效,但我已经看到了一些类似的答案,这些答案实际上并不适合我的用例。因为这里写的东西的含义对我来说很难理解,我只会提及并询问“您认为通用lambda会破坏此功能吗?”(注意:另外,该建议链接现在已失效…@HostileFork它可能会破坏。虽然它使用固定类型正确处理函数和lambda,但它会在出现重载或模板时立即破坏,因为它
&T::operator()
无法解析重载函数的地址。底线是,如果您可以抽象出函数的类型,请这样做,然后如果其他方法都不起作用,您可以尝试使用
函数特性
(请注意,它们也存在于Boost中)。死链接是指向一个问题的链接,该问题还提供了一些功能特性。尽管我使用了(可能有点复杂),但将您的挑战向上投票给向下投票人并给出答案。我很好奇你对它的想法,如果加上任何曲线球,因为在我的简短调查中,他们被提到在解决这个问题时击败了一些黑客(尽管很难找到一个没有人说“这不是你真正想要的”)的问题。@HostileFork:我想你不能使用
decltype(&F::operator())
,因为该成员函数是一个模板。
template <typename C, typename R, typename ...Args>
struct remove_member<R (C::*)(Args...) const>
{ using type = R(Args...); };
template<std::size_t...>
struct indices {};

template<std::size_t N, std::size_t... Ind>
struct make_indices:
    make_indices<N-1, N-1, Ind...>
{};

template<std::size_t... Ind>
struct make_indices<0, Ind...>:
    indices<Ind...>
{};
template<typename T>
struct function_traits:
    function_traits<decltype(&T::operator())>
{};

template<typename C, typename Ret, typename... Args>
struct function_traits<Ret(C::*)(Args...) const>
{
    enum { arity = sizeof...(Args) };

    using result_type = Ret;

    template<std::size_t N>
    using arg = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
template<typename Function, std::size_t... Ind>
auto make_foo_(Function&& func, indices<Ind...>)
    -> Foo<
        typename function_traits<typename std::remove_reference<Function>::type>::result_type,
        typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...>
{
    using Ret = typename function_traits<typename std::remove_reference<Function>::type>::result_type;
    return { std::function<Ret(typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...)>(func) };
}

template<typename Function, typename Indices=make_indices<function_traits<typename std::remove_reference<Function>::type>::arity>>
auto make_foo(Function&& func)
    -> decltype(make_foo_(std::forward<Function>(func), Indices()))
{
    return make_foo_(std::forward<Function>(func), Indices());
}
int main()
{
    auto lambda = [](int i, float b, long c)
    {
        return long(i*10+b+c);
    };

    auto foo = make_foo(lambda);
    std::cout << foo(5, 5.0, 2) << std::endl; // 57, it works!
}