Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/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回调取决于其参数_C++_Lambda_Template Meta Programming - Fatal编程技术网

C++ Lambda回调取决于其参数

C++ Lambda回调取决于其参数,c++,lambda,template-meta-programming,C++,Lambda,Template Meta Programming,我正在编写一个库,其中用户以lambda的形式提供回调。在默认情况下,我只想调用lambda并将其传回一个对象 现在,用户可能还需要上下文,这是非常重要的。因此,我希望能够使用相同的回调机制,只允许用户将上下文作为参数添加到lambda中,然后我将传递对象和上下文 我不能让斯芬娜去工作 我已将代码简化为: #include <string> #include <iostream> class Context {}; template<typename F>

我正在编写一个库,其中用户以lambda的形式提供回调。在默认情况下,我只想调用lambda并将其传回一个对象

现在,用户可能还需要上下文,这是非常重要的。因此,我希望能够使用相同的回调机制,只允许用户将上下文作为参数添加到lambda中,然后我将传递对象和上下文

我不能让斯芬娜去工作

我已将代码简化为:

#include <string>
#include <iostream>

class Context {};


template<typename F>
struct UseContext
{
    // I want to set this value to 0 or 1 based on the parameters
    // in F but can't quite get this to work.
    enum {value = 0 };
};


template<typename F, typename T, bool useContext = UseContext<F>::value>
struct Caller;

template<typename F, typename T>
struct Caller<F, T, true>
{
    void operator()(F& func, Context& context, T& object)
    {
        func(context, object);
    }
};
template<typename F, typename T>
struct Caller<F, T, false>
{
    void operator()(F& func, Context&, T& object)
    {
        func(object);
    }
};



template<typename T, typename F>
void doWork(F&& func)
{
  Context  context;
  T        object;

  /// STUFF
  Caller<F,T>  caller;
  caller(func, context, object);
}
#包括
#包括
类上下文{};
模板
结构UseContext
{
//我想根据参数将此值设置为0或1
//在F中,但不能完全实现这一点。
枚举{value=0};
};
模板
结构调用方;
模板
结构调用程序
{
void操作符()(F&func,Context&Context,T&object)
{
func(上下文、对象);
}
};
模板
结构调用程序
{
void运算符()
{
func(对象);
}
};
模板
无效工作(F&func)
{
语境;
T对象;
///东西
呼叫者;
调用者(函数、上下文、对象);
}
用法:

int main()
{
    // if UseContext::value == 0 then this compiles.
    // This is the normal situation.
    doWork<std::string>([](std::string const& x){ std::cout << x << "\n";});

    // if UseContext::value == 1 then this compiles.
    // This is if the user wants more context about the work.
    // most of the time this extra parameter is not required.
    // So I don't want to force the user to add it to the parameter
    // list of the lambda.
    doWork<std::string>([](Context&, std::string const& x){ std::cout << x << "\n";});
}
intmain()
{
//如果UseContext::value==0,则编译。
//这是正常情况。
doWork([](std::string const&x){std::cout表达式SFINAE:

template<class F, class T>
auto call(F& func, Context& context, T& object) -> decltype(func(context, object), void())
{
   func(context, object);
}
template<class F, class T>
auto call(F& func, Context&, T& object) -> decltype(func(object), void())
{
    func(object);
}
模板
自动调用(F&func,Context&Context,T&object)->decltype(func(Context,object),void())
{
func(上下文、对象);
}
模板
自动调用(F&func,Context&T&object)->decltype(func(object),void())
{
func(对象);
}

然后只调用(func、context、object)
。如果两种形式都有效,这是不明确的。如果要消除歧义,只需添加一个伪参数,然后执行通常的
int
/
long
技巧。

我的解决方案是使用
std::is_constructible
加上
std::enable_if
:

template<typename F,typename T>
typename std::enable_if<std::is_constructible<std::function<void(T const&)>,F>::value>:type doWork(F func)
{
//...
}

template<typename F,typename T>
typename std::enable_if<std::is_constructible<std::function<void(Context&,T const&)>,F>::value>:type doWork(F func)
{
//...
}
模板
typename std::enable_if:type doWork(F func)
{
//...
}
模板
typename std::enable_if:type doWork(F func)
{
//...
}

解释-每个
std::function
都可以从相同的lambda构建。这里我们使用
std::enable_if
进行测试,如果您可以构建
std::function
std::function
并在编译时重新连接正确的函数。

如果用户需要上下文,他可以在capt中捕获它作为参考吗ure list?对于我来说,作为一个可能使用这个库的人,它更直观。想要一些上下文吗?捕获它作为参考。@DavidHaim:你不能,因为上下文在调用
doWork()
的点不可用。它来自库内部。捕获列表捕获上下文在创建lambda的点(不是在使用它的地方)。我现在理解了你的问题,这似乎很容易:-)@loki注意,在msvc 2013 2025中,这可能不起作用,因为它属于“表达式SFINAE”。但是,我认为有一个标记分派变体。对于那些不喜欢逗号运算符的人,可以使用
std::result\u of