为什么主表达式不包含template_id

why primary expression don't include template_id

本文关键字:template id 包含 表达式 为什么      更新时间:2023-10-16

我有这样的代码,用"g++ -Wall -g -std=c++11 test.cpp "编译,由于错误:')'标记前期望主表达式

而无法编译
#include <functional>
#include <vector>
#include <algorithm>
int main()
{
  std::vector<int> vec;
  for(int i=0;i<10;++i)
    {
      vec.push_back(i);
    }
  std::sort(vec.begin(),vec.end(),std::less<int>);  //should be std::less<int>()
}

但是标准说:

primary-expression:
  literal
  this
  ( expression )
  id-expression
  lambda-expression
id-expression:
  unqualified-id
  qualified-id
unqualified-id:
  identifier
  operator-function-id
  conversion-function-id
  literal-operator-id
  ~ class-name
  ~ decltype-specifier
 template-id
template-id
  simple-template-id
simple-template-id
  template-name <template-argument-list> 

所以看起来std::less是一个模板id,所以它是一个主表达式

语法正确并不一定使程序语义正确。primary-expression -> template-id的语法结果允许将函数模板的专门化用作表达式,例如:

template <typename T>
bool less(const T& a, const T& b) { return a < b; }
int main() {
  std::vector<int> vec;
  std::sort(vec.begin(), vec.end(), less<int>);
}

引用类模板的template-id不能作为表达式使用。

这是解析器和语义分析器之间的区别。c++的语法只告诉你什么是合乎语法的——什么将通过解析器。例如,该语法还允许您执行以下操作:

std::sort(vec.begin(), vec.end(), ~MyClass);

出于同样的原因——因为~ class-nameunqualified-id。您需要查看语言的语义规则来确定程序是否格式良好,而不仅仅是查看语法,并且语言的语义规则在这里需要一个值,而不是一个类型。


具体来说,我相信标准通过c++ 11 5.2.2 [expr]中的函数调用操作符(())规则来说明这一点。(强调我的)

调用函数时,每个形参 (8.3.5) 都要用对应的实参初始化 (8.5, 12.8, 12.1)
(dcl

8.5。/1:(强调我的)

声明器可以为被声明的标识符指定一个初始值。标识符指定要初始化的变量

但我不是标准学者,我也不是委员会成员,所以YMMV。

老实说,我还没有从表达式的角度考虑过这个问题。但是我考虑它的方式- std::sort想要一个对象作为它的第三个参数。std::less<int>只是一个类型声明。std::less<int>()创建std::sort需要的对象