【问题标题】:Omitting type parameter for greater template in C++ STL在 C++ STL 中省略更大模板的类型参数
【发布时间】:2018-06-04 18:50:12
【问题描述】:
这是我在书中读到的一行代码
priority_queue<IteratorCurrentAndEnd, vector<IteratorCurrentAndEnd>, greater<>> min_heap;
其中IteratorCurrentAndEnd 是一个实现operator> 方法的类。为什么我们可以有greater<> 而不是greater<IteratorCurrentAndEnd>?我检查并阅读了类似的内容,
template< class T = void >
struct greater;
但我真的不知道这意味着什么。它与void 类型有关吗?它到底是什么?
谢谢。
【问题讨论】:
标签:
c++
c++11
stl
generic-programming
function-object
【解决方案1】:
在 C++14 之前,std::greater<T> 是基于一个显式类型参数 T 的类模板。它只允许比较两个相等的类型。否则,在比较不同的类型时,必须依赖转换,这在模板参数推导过程中可能会失败。
这已在 C++14 中得到修复,因为现在还存在两种不同类型的一般比较。没有使用新的类模板std::greater<T,U>(它可能不会向后兼容,当然也更复杂),而是使用了在 C++14 之前不存在的专门化 std::greater<void>。选择 void 类型正是出于这个原因:因为它在 C++14 之前从未使用过——比较 voids 没有意义——自动获得向后兼容性,甚至避免引入新的类模板。
正如reference 中所述,std::greater<void> 现在是一个函子,其中包含一个类似于
的
operator() 函数模板
template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
{
return std::forward<T>(lhs) > std::forward<U>(rhs);
}
这实现了两种类型之间的一般比较(和现在想出的完全一样)。
【解决方案2】:
是的,它与 sn-p 中的void 相关,但 void 作为类型本身并没有什么特别之处。该语法表示struct greater 采用一个模板参数(即一种类型),但它可以省略,如果省略,void 将用作该类型。它类似于常规函数的默认值语法:
void foo(int x = 7);
foo(5); // x = 5
foo(); // x = 7