C++函子的类模板专用化

C++ class template specialization for functors

本文关键字:专用 C++      更新时间:2023-10-16

std::set具有以下模板参数:

template<typename _Key, typename _Compare = std::less<_Key>,
typename _Alloc = std::allocator<_Key> >
class set

std::greater具有以下模板参数:

template<typename _Tp>
struct greater : public binary_function<_Tp, _Tp, bool>

以下声明都可以在 gcc 7.1 上编译。我不明白为什么第二个声明是有效的。它是 C++14 功能吗?规则是否在标准的某处定义?

std::set<int, std::greater<int>> s1;
std::set<int, std::greater<>> s2;

它是一个 C++14 标准库功能,称为透明比较器。

以下声明都可以编译

std::set<int, std::greater<int>> s1;
std::set<int, std::greater<>> s2;

第二种变体允许异构比较。在int的情况下没什么大不了的,但考虑一下 N3657 中的示例:

std::set<std::string> s = /* ... */;
s.find("key");

在旧的 C++11 中,这将构造一个临时string,以便 调用less(string, string)

在C++14中使用透明比较器,将自动生成less::operator() (const string&, const char*)1,这将调用bool operator< (const string&, const char*),从而避免了临时性。

它的实现方式是:

template< class T = void >
struct greater;
template <> struct greater<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) > std::forward<U>(u));
};

也就是说,当未指定T时,它默认为void,在 C++14 中具有接受异构参数的专用化。这里的假设是没有人会在旧代码中使用std::greater<void>,因此现有代码破译的风险很小。

有关更多详细信息,请参阅介绍"钻石运营商"的提案 N3421 和介绍std::is_transparent的 N3657 。


1免责声明:确切的推导类型可能不同,这只是为了说明核心概念,而不涉及太多细节。

它是 C++14 功能吗?

是的,它是:

template< class T >
struct greater; // Until C++14
template< class T = void >
struct greater; // Since C++14

如果未指定类型T,它将获得默认值void

规则是否在标准的某个地方定义?

从比较中:

template<class T = void> struct greater {
constexpr bool operator()(const T& x, const T& y) const;
};