C++里也有菱形运算符?
最近在翻《c++函数式编程》的时间看到有一小节在说c++14新增了“菱形运算符”。我寻思c++里似乎没什么运算符叫这名字啊,而且c++14新增的功能很少,我也不记得有添加这种语法特性。一瞬间我有些怀疑我的记忆了,所以为了查漏补缺,我写了这篇文章。什么是菱形运算符
这个概念在Java里比力多见:
List<String> myList = new ArrayList<>();这东西在Java里的学名是diamond operator,表示利用泛型类而且范例参数在左侧的表达式已给出因此在右侧可以省略。
简单的说就是让你少写频频重复的范例参数。因为看起来像个菱形所以得名菱形运算符。
然后我们偶尔会在c++里看到外形上很相似的东西:
std::sort(vec.begin(), vec.end(), std::greater<>());出现在模板的特化中是我们所熟悉的,但这个std::greater()是什么呢?
c++没有菱形运算符
先说结论,从语言标准来说,c++里没有什么菱形运算符。
c++20里虽然新增了一个运算符operator,但这个和所谓的菱形运算符没有任何关系。
那题目来了,std::greater()是什么以及为什么书里说是c++14新增的特性呢?难道书里瞎说的吗?但事实是这样的示例代码在c++14以及之后的标准下可以正常编译运行,而且这本书的质量尚可,虽然会在措辞上犯些小错(比如c++没有菱形运算符)但不至于花大篇幅去胡说八道。
当然,要想回答这个题目我们得先复习点底子知识。
在c++里的作用
先说结论,在c++里看到,绝大多数都是在为模板提供范例参数,当然这种东西我们不讨论:(ab),这里是在两个不同的表达式里。
那既然用来提供范例参数,那为什么可以啥都不提供呢?答案是有两类情况确实可以。
第一类是在函数模板上,范例参数可以自动推导时:
template <typename T>
void f(const T&)
{
std::cout << "f<T>\n";
}
template <>
void f(const int&)
{
std::cout << "f<int>\n";
}
void f(const int&)
{
std::cout << "f\n";
}
int main()
{
f(1); // f
f<>(1);// f<int>
f(1.2);// f<T>
}当利用std::greater()的时间,代码的逻辑和原来一样,当利用std::greater()的时间,返回的Functor的函数调用运算符是个模板,可以自己推导参数范例和返回值范例。至于为啥greater的内部构造可以和其他情况实例化的greater区别这么大,这个是c++的特性:模板的不同实例之间是可以异构的。
而且因为范例参数的默认值就是void,因此可以简写成std::greater()。
所以c++14只是给标准库里可以代替运算符的模板们增加了默认范例参数和一个泛型的调用运算符,利用这些可以简化代码并确保范例安全。
原形是其实没啥菱形运算符,只是利用了以前就存在的模板的特性简化了标准库的利用,让人少写点字。达成的效果倒是和Java的菱形运算符差不多。
总结
显然书里有夸大成分,老话说尽信书不如无书,还得小心检验才是。
顺便我们复习了现代c++的重要原则:能依赖自动范例推导的地方,没必要自己手写。
因此应该多写这样的代码:std::sort(vec.begin(), vec.end(), std::greater<>());。
不过尚有最后一个题目,为啥不直接用lambda呢?那是因为能指定范例参数的泛型lambda要在c++20才出现,在这之前想要让lambda完全做到范例安全得费点功夫,而且lambda团体上也不如直接用标准库提供的std::greater()、std::less()之类的简洁易懂。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]