C++ 为什么主表达式不';不包括模板id

C++ 为什么主表达式不';不包括模板id,c++,bnf,C++,Bnf,我有这样的代码,用“g++-Wall-g-std=c++11 test.cpp”编译,它没有编译,因为错误:在“')”标记之前应该有主表达式 #包括 #包括 #包括 int main() { std::vec; 对于(int i=0;i老实说,我没有从表达式的角度考虑这一点。但是我的思考方式-std::sort需要一个对象作为它的第三个参数。std::less只是一个类型声明。std::less()创建std::sort所需的对象。这是语法分析器和语义分析器之间的区别。C++的语法只告诉您什么是

我有这样的代码,用“g++-Wall-g-std=c++11 test.cpp”编译,它没有编译,因为错误:在“')”标记之前应该有主表达式

#包括
#包括
#包括
int main()
{
std::vec;

对于(int i=0;i老实说,我没有从表达式的角度考虑这一点。但是我的思考方式-
std::sort
需要一个对象作为它的第三个参数。
std::less
只是一个类型声明。
std::less()
创建
std::sort
所需的对象。

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

std::sort(vec.begin(), vec.end(), ~MyClass);
出于同样的原因——因为
~类名
是一个
非限定id
。您需要查看语言的语义规则,以确定程序是否格式正确,而不仅仅是查看语法,并且语言的语义规则需要此处的值,而不是类型


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

调用函数时,应使用相应的参数初始化每个参数(8.3.5)8.5,12.8,12.1)

8.5[dcl.init]/1:(强调矿山)

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


但我不是标准学者,也不是委员会成员,因此语法正确并不一定会使程序语义正确。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>);
}
模板
bool-less(常数T&a,常数T&b){返回a

但是,引用类模板的模板id不能用作表达式。

您使用的是哪种编译器?FWIW,Clang:error:expected'('对于函数样式转换或类型construction@MantoshKumar,可能是GCC.4.9给出了错误。看来编译错误消息中有问题。我在VS2010中运行了相同的程序,得到了以下“错误C2275:'std::less':非法使用此类型作为表达式”@MantoshKumar,这个铿锵错误没有错。它基本上是说“你有一半这种类型的表达式,但你缺少了另一半”+ 1。语义和语法的差别在最好的时候是微妙的,在C++中更是如此。标准没有区分不同格式的不完善的程序:它只是定义了一个格式良好的程序,作为一个“根据语法规则、可诊断语义规则和一个定义规则构造的C++程序”。,而一个格式不正确的程序则是一个格式不正确的程序。@Casey。我几乎同意你的看法。我认为该程序在语义上是错误的,但它确实是一个主表达式,那么这是否意味着g++报告了一个错误类型的错误?看来clang的错误代码“非法使用此类型作为表达式”更为合理。
std::sort(vec.begin(), vec.end(), ~MyClass);
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>);
}