c++ - 在参数推导过程中,泛型 lambda、模板函数和模板成员 operator() 之间的主要区别是什么?
问题描述
与算法一起使用时,我对以下差异感到困惑。
首先,算法可以毫无问题地使用 lambda、函数和仿函数。例如,
bool comp (int t1, int t2) {
return t1 > t2;
}
std::array<int, 10> myArray{5, -10, 3, 2, 7, 8, 9, -4, 3, 4};
std::sort(myArray.begin(), myArray.end(), comp);
现在让我们定义模板比较器,
template<typename T>
bool comp1(T t1, T t2) {
return t1 > t2;
}
struct Comp {
template<typename T>
bool operator()(T t1, T t2) const {
return t1 > t2;
}
};
Comp comp2;
auto comp3 = [](auto t1, auto t2) { return t1 > t2; }
template<typename Container>
void sortDescending(Container &c) {
std::sort(c.begin(), c.end(), comp1); // cannot deduce argument error
std::sort(c.begin(), c.end(), comp2); // works
std::sort(c.begin(), c.end(), comp3); // works
}
sortDescending(myArray);
函数模板在上述场景中不起作用,这让我很困惑。
对我来说,至少 comp1 和 comp2 几乎相同(在某种意义上,推断参数所需的信息量)。但是 comp1 不起作用。
所以我的问题是,这种差异背后的最终原因是什么?
即,就参数推导而言,函数模板、模板 operator()(模板仿函数?)和通用 lambda 之间的主要区别是什么?
谢谢。
解决方案
模板是 C++ 的一种语言构造,它生成其他构造:类、函数或变量(在 C++14 中)。没有模板参数的模板名称只能以非常有限的方式使用。
comp1
命名模板,而不是函数。这是重要的一点。函数模板是在您提供特定模板参数时生成函数的构造;comp1<int>
是函数的名称。但名称本身命名模板,而不是它生成的函数。
函数模板的名称可以被调用(即:)comp1(arg1, arg2)
,因为 C++ 的一个特殊规则称为“模板参数推导”。简而言之,编译器根据提供给函数调用的参数comp
的声明comp
和性质推断模板参数的类型。但这仅有效,因为 C++ 有一条规则表明它确实有效。
单独的模板名称(如comp1
)不是表达式,函数调用期望表达式(或花括号初始化列表)作为参数给出。错误“无法推断参数错误”不是关于 std::sort
; 这是关于为 自己推断模板参数std::sort
。comp1
,一个模板,没有类型,所以它不能参与参数推导。
comp2
命名一个变量,就像comp3
. 这两个都是表达式,所以都可以传递给函数。
是的,两者的类型都comp2
包含comp3
一个函数模板。但是comp2
,comp3
作为名称命名变量,而不是它们包含的函数模板。所以它们像任何其他变量一样工作。
至于泛型 lambda,它与任何其他具有模板方法的用户定义类型没有什么不同。operator()
推荐阅读
- autodesk-forge - 在firefox的forge查看器中禁用触摸板上的页面滚动滚动
- python - SQLAlchemy 警告:列不会成为声明性映射的一部分
- javascript - JS/DOM,性能:您是否应该尝试使用尽可能少的事件侦听器?
- r - 格式化 geom_tile ggplot2 内堆叠 geom_bar 的内部行
- flutter - flutter - 查看容器内的网页
- text - 谷歌语音是否有任何 URL 结构可以准备好数字输入?
- r - 非线性最小二乘故障排除
- .net - 将 .net core 2.2 升级到 3.0
- c++ - 如何将指针传递给指针向量?
- python - 将 tf-idf 与 FastText 向量一起使用