C++ lambda 表达式作为函数模板中的参数

C++ lambda expression as an argument in function template

本文关键字:参数 函数模板 lambda 表达式 C++      更新时间:2023-10-16

我需要定义一个函数,该函数将集合和一个函数作为输入,以完成集合的漂亮打印。就此而言,我想明确指定函数的类型,以便编译器可以递归匹配,从而签名

template<typename T, PrettyPrinter>
std::string to_string(const std::set<T>& set, PrettyPrinter printer);

不够精确,因为编译器无法推断所需函数对象的类型。所以相反,我想使用显式类型

template<typename T>
std::string PrettyPrinting::to_string(const std::set<T>& set, std::function<std::string(const T&)> printer){
    const char* separator = ", ";
    const char* leftDelimiter = "{";
    const char* rightDelimiter = "}" 
    std::string output = leftDelimiter;
    if(set.begin() == set.end()) return output + rightDelimiter;
    typename std::set<T>::const_iterator it = set.begin();
    output += printer(*it);
    for(++it; it != set.end(); it++) output.append(separator) += printer(*it);
    return output + rightDelimiter;
}

这符合我的预期。但是,我不能在另一个模板结构中使用 lamba 表达式

std::string to_string(const std::set<std::string>& set){
    return to_string(set, [](const std::string& input){ return input; });
}

我得到一些奇怪的错误,即lambda函数不是合适的参数。另一方面,以下代码有效

inline std::string to_string(const std::set<std::string>& set){
   std::function<std::string(const std::string&)> printer = [](const std::string& input){ return input; };
   return to_string(set, printer);
}

编译器需要显式函数对象有什么合理的理由吗?我应该将什么指定为类型,以便可以直接将 lambda 表达式编写为函数参数?

Lambdas和std::function<...>是两种不同的类型。模板参数推导不关心隐式转换。试试这个:

template<typename T, typename PrintLambda, typename = std::enable_if_t<std::is_convertible<PrintLambda, std::function<std::string(const T&)> >::value >>
std::string PrettyPrinting::to_string(const std::set<T>& set, PrintLambda printer);

以上通过检查PrintLambda是否可以转换为适当的std::function来确保它具有正确的签名。