为何模板函数可作为std::sort参数,模板lambda却无法使用?
模板Lambda传递给std::sort的语法问题
问题描述
以下基于模板函数的代码可正常运行,实现按结构体S的b成员排序:
#include <algorithm> #include <iostream> #include <vector> struct S { int a{}, b{}; }; std::ostream &operator<<(std::ostream &o, const S &s) { return o << '{' << s.a << ',' << s.b << '}'; } template <auto ptr> bool f(const S &a, const S &b) { return a.*ptr < b.*ptr; } int main() { std::vector<S> v{{1,9},{2,8},{3,7},{4,6},{6,4},{7,3},{8,2},{9,1}}; std::sort(v.begin(), v.end(), f<&S::b>); for (const auto &s : v) std::cout << s << ' '; return 0; }
但改用模板Lambda时,编译器会误将模板参数语法<&S::b>解析为小于运算符,导致编译失败:
// 续上面的main函数 auto l = []<auto ptr>(const S &a, const S &b) { return a.*ptr < b.*ptr; }; std::sort(v.begin(), v.end(), l<&S::b>); // 此处编译报错
报错信息:
error: no match for 'operator<' (operand types are 'main()::<lambda(const S&, const S&)>' and 'int S::*') std::sort(v.begin(), v.end(), l<&S::b>); ~^~~~~~
解决方案
方法1:显式调用模板化operator()并包装为普通Lambda
模板Lambda的模板参数定义在operator()成员函数上,需用.template关键字明确告知编译器后续的<是模板参数列表而非小于运算符,将其包装为普通Lambda后传递给std::sort:
std::sort(v.begin(), v.end(), [&l](const S& a, const S& b) { return l.template operator()<&S::b>(a, b); });
方法2:直接在std::sort参数中定义带默认模板参数的Lambda
若无需复用该模板Lambda,可直接在std::sort参数内定义Lambda并指定默认模板参数,简化写法:
std::sort(v.begin(), v.end(), []<auto ptr = &S::b>(const S& a, const S& b) { return a.*ptr < b.*ptr; });
方法3:获取模板化operator()的实例地址
直接通过.template operator()<&S::b>获取模板实例化后的可调用对象地址,传递给std::sort:
std::sort(v.begin(), v.end(), l.template operator()<&S::b>);
内容的提问来源于stack exchange,提问作者PaperBirdMaster
相关产品推荐
相关产品推荐

