首页 > 解决方案 > 如何在元组中正确存储 lambda 函数并调用它们?

问题描述

我正在尝试创建一个可以将函数存储在成员元组中的类。但是当试图将 lambdas 放在对象的元组中(通过函数指针)时,我遇到了一个错误。请解释一下,我做错了什么以及发布这个想法的正确方法是什么。我认为应该有一个优雅且风格正确的通用解决方案(就函数式编程模式而言),以避免在类描述、对象创建和用函数填充它们中使用样板代码。

#include <functional>
#include <string>
#include <iostream>

template<typename... ArgTypes> 
class MyClass {
public:
    //boolean function of some argument
    template<typename Type> using Func = bool(Type const &);

    //type for a tuple of pointers to templated boolean functions
    template<typename... Types> using TupleOfFunctions = typename std::tuple<Func<Types>*...>;
    
    //the tuple
    TupleOfFunctions<ArgTypes...> _tuple;
    
    //constructor
    MyClass(TupleOfFunctions<ArgTypes...> t) : _tuple(t) {  
    }
};

int main(int argc, char** argv) {
    MyClass<int, std::string> M({
        [](int &arg) { return arg > 0; },
        [](std::string &arg) { return arg == "abc"; }
    });
    
    std::cout << (*std::get<0>(M._tuple))(1);
    std::cout << (*std::get<1>(M._tuple))("xyz");
    
    return 0;
}

我得到的错误是

./test.cpp:26:3: error: no matching function for call to 'MyClass<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::MyClass(<brace-enclosed initializer list>)'
   26 |  });

标签: c++c++11

解决方案


template<typename Type> using Func = bool(Type const &);

这一行建议使用const类型参数的函数。然而:

[](int &arg) { return arg > 0; },
[](std::string &arg) { return arg == "abc"; }

这两行建议非常量参数。

要么const从第一行删除,要么添加const到第二行应该解决它。


但是,您能否提出一些重新设计类的想法,以便避免重复显式声明这些类型(在类模板规范和 lambda 函数参数中)的样板代码?

拥有 lambda 的部分原因是匿名函数类型。实际上,像你所做的那样,试图推断出其中的一种,有点倒退。

我建议这样做的一种方法是:

template<typename ... Lambdas> 
class MyClass {
public:
    std::tuple<Lambdas...> _tuple;
    
    MyClass(Lambdas ... args) : _tuple(std::make_tuple(args ...)) {  
    }
};

现在你可以像这样使用它:

MyClass M(
    [](const int &arg) { return arg > 0; },
    [](const std::string &arg) { return arg == "abc"; }
);

或者,您可能对变体/访问模式感兴趣:https ://godbolt.org/z/5Pdn1Ynqe


推荐阅读