У меня есть такой код, скомпилируйте с помощью «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 — это идентификатор шаблона, поэтому это первичное выражение.
Быть грамматически правильным не обязательно делает программу семантически правильный. Создание грамматики из 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>);
}
Однако идентификатор шаблона, который ссылается на шаблон класса, не может использоваться в качестве выражения.
В этом разница между анализатором и семантическим анализатором. Грамматика 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.
Честно говоря, я не думал об этом с точки зрения выражений. Но то, как я думаю об этом — std::sort
хочет объект для своего третьего параметра. std::less<int>
это просто объявление типа. std::less<int>()
создает объект, который std::sort
требует.