我有这样的代码,使用" 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,因此它是一个主要表达式。
答案 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-name
是unqualified-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
所需的对象。