函数模板接受并返回不同的lambdas [英] Function template accept and return different lambdas

查看:16
本文介绍了函数模板接受并返回不同的lambdas的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的函数GetThing如下:

auto GetThing(size_t index, auto&& l1)
{
    return l1;
}
auto GetThing(size_t index, auto&& l1, auto&&... rest)
{
    if (index == 0)
        return l1;
    return GetThing(index - 1, rest...);
}

我希望它也能够处理不同的lambdas,同时能够处理其他类型(即非lambdas、非函数,如int和...),如

std::cout << GetThing(1, 2, 3, 4);   //works, return 3
std::cout << GetThing(1, [] {return 0; }, 
    [] {return 1; }, [] {return 2; }, 
    [] {return 3; } )();             //nope

但这里的问题是lambda是不同类型的,因此递归函数会演绎为不兼容的返回类型,所以我似乎不得不这样使用std::function,但它很难看。

std::cout << GetThing(1, std::function{ [] {return 0; } }, std::function{ [] {return 1; } }, std::function{ [] {return 2; } }, std::function{ [] {return 3; } })();//works

解决此问题的任何可能方法,例如,如果存在重载的operator(),则它会自动将类型强制为std::function

编辑:我知道无捕获的lambdas可以转换为函数指针,但如何在模板中没有std::decay的情况下推导出它?因为我仍然希望将其他类型作为引用进行处理

EDIT2:我收到了一些使用std::variant的答案,我在想,除了lambda,参数类型应该是相同的,例如。std::variant<int, int, int>可以向GetThing添加重载,这样当std::variant持有相同类型时,它将返回该类型的内容,否则(接收lambdas的情况)将返回std::function

推荐答案

您可以将函数存储在变量数组中。当然,这也带来了一些开销。但这使函数也可以使用捕获的变量。

这使您能够从这样的函数集合中选择一个函数,并使用给定的参数执行它,如下所示:

template < typename ARR_T >
struct Collect
{
    template < typename ... T > 
    Collect( T&&...args  ): arr{std::forward<T>(args)...}{}
    ARR_T arr;
    using VARIANT_T = ARR_T::value_type;
    VARIANT_T& operator[]( size_t index) { return arr[index]; }
};

template < typename ... T > 
Collect( T&& ... args ) -> Collect< std::array< std::variant<T... >, sizeof...(T) >>; 

template < typename C, typename ... PARMS >
auto GetThing( size_t index, C&& c, PARMS&&... parms ) 
{
    return std::visit( [ &parms...]( auto&& func)
                      {
                          return func(std::forward<PARMS>(parms)...);
                      }, c[index]);
}

int main()
{
    std::cout << GetThing( 2, Collect(  []( int, double) {return 0; }, []( int, double) {return 1; }, []( int, double) {return 2; }, []( int, double) {return 3; }), 1,5.6)<< std::endl;

    int y = 8;
    double d = 9.99;

    std::cout << GetThing( 0, Collect(  [y,d]( int, double) {return d*y; }, []( int, double) {return 1.; }, []( int, double) {return 2.; }, []( int, double) {return 3.; }), 1,5.6)<< std::endl;
}



在本例中GetThing还获取用于调用lambda的函数参数,因为调用使用std::visit。如果您只想选择该函数(&Q;),您将获得std::variant(如果您喜欢),并且可以自己调用该函数。


    auto func = Collect(  []( int i, double d) {return d+i; }, []( int i, double d) {return d*i; }, []( int i, double d) {return d-i; } )[2];
    std::cout << std::visit( []( auto&& f) { return f( 9, 7.77 ); }, func ) << std::endl;
}

这篇关于函数模板接受并返回不同的lambdas的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆