仿函数的C ++类模板专业化

时间:2018-04-10 05:49:09

标签: c++ templates c++14

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;

3 个答案:

答案 0 :(得分:3)

  

它是C ++ 14的功能吗?

Yes, it is

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

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

如果未指定类型T,则会获得默认值void

答案 1 :(得分:3)

这是一个名为transparent comparators的C ++ 14标准库功能。

  

以下声明都可以编译

           d            | to_char
------------------------+---------
 2018-02-09 08:17:17+00 | 2018_02
 2018-03-09 08:17:17+00 | 2018_03
(2 rows)

第二种变体允许进行异构比较。在std::set<int, std::greater<int>> s1; std::set<int, std::greater<>> s2; 的情况下没什么大不了的,但请考虑N3657的例子:

int

在旧的C ++ 11中,这将构造一个std::set<std::string> s = /* ... */; s.find("key"); 临时代码 调用string

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

它的实施方式是:

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,它在C ++ 14中具有接受异构参数的特化。这里的假设是没有人会在旧代码中使用void,因此现有代码破解的风险很小。

有关详细信息,请参阅提案N3421,其中介绍了&#34;钻石运营商&#34;和N3657,其中介绍了std::greater<void>

1 免责声明:确切的推断类型可能有所不同,这只是为了说明核心概念而不会过多详细说明。

答案 2 :(得分:1)

  

规则是否在标准的某处定义了?

来自comparisons.greater

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