为什么主要表达不包括template_id

时间:2014-06-26 16:41:53

标签: c++ bnf

我有这样的代码,使用" g ++ -Wall -g -std = c ++ 11 test.cpp"编译,因为错误:在'之前预期的primary-expression' )'令牌

#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,因此它是一个主要表达式。

3 个答案:

答案 0 :(得分:4)

语法正确并不一定使程序在语义上正确。初级表达的语法产生 - &gt; 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不能用作表达式。

答案 1 :(得分:2)

这是解析器和语义分析器之间的区别。 C ++的语法只告诉你什么是语法 - 什么会通过解析器。例如,语法也允许你做类似的事情:

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

出于同样的原因 - 因为~ class-nameunqualified-id。您需要查看语言的语义规则以确定程序是否格式正确,而不仅仅是查看语法,语言的语义规则需要一个值,而不是类型。


具体来说,我相信标准通过C ++ 11上的函数调用运算符(())的规则来说明这一点5.2.2 [expr.call] / 4 :(强调我的)

  

调用函数时,每个参数(8.3.5)应初始化 8.5 ,12.8,12.1)及其对应参数。

8.5 [dcl.init] / 1 :(强调我的)

  

声明者可以为声明的标识符指定初始值。 标识符指定正在初始化的变量

但我不是标准学者而且我不参加委员会,所以YMMV。

答案 2 :(得分:0)

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