почему основное выражение не включает template_id

У меня есть такой код, скомпилируйте с помощью «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 — это идентификатор шаблона, поэтому это первичное выражение.

3

Решение

Быть грамматически правильным не обязательно делает программу семантически правильный. Создание грамматики из 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>);
}

Однако идентификатор шаблона, который ссылается на шаблон класса, не может использоваться в качестве выражения.

4

Другие решения

В этом разница между анализатором и семантическим анализатором. Грамматика 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

Честно говоря, я не думал об этом с точки зрения выражений. Но то, как я думаю об этом — std::sort хочет объект для своего третьего параметра. std::less<int> это просто объявление типа. std::less<int>() создает объект, который std::sort требует.

0
По вопросам рекламы [email protected]