Когда все оператор запятой не действует как оператор запятой?
Если вы видите этот код,
class A{
public:
A(int a):var(a){}
int var;
};
int f(A obj) {
return obj.var;
}
int main() {
//std::cout<<f(23); // output: 23
std::cout<<f(23, 23); // error: too many arguments to function 'int f(A)'
return 0;
}
f(23, 23)
не компилируется, потому что запятая действует здесь как разделитель, а не как оператор запятой.
Где все запятая не работает как оператор запятой? Или наоборот?
5 ответов
С грамматической точки зрения параметры вызова функции образуют необязательный список выражений в скобках. Список выражений состоит из одного или нескольких выражений присваивания, разделенных токеном запятой. Запятая может обозначать только оператор запятой, где ожидается выражение.
Оператор запятой делает выражение из выражения, ,
и выражение присваивания, но выражение, включающее оператор запятой, само по себе не является выражением присваивания, поэтому не может появляться в списке выражений, кроме случаев, когда оно является составной частью чего-либо, что является выражением присваивания.
Например, вы можете заключить любое выражение (включая выражение, использующее оператор запятой) в круглые скобки в первичное выражение, которое является выражением присваивания и, следовательно, допустимым в списке выражений.
Например
Постфиксное выражение, где список выражений состоит из двух выражений присваивания, каждое из которых является идентификатором.
f( a, b );
Постфиксное выражение, где список выражений состоит из одного выражения присваивания, которое является первичным выражением, которое является выражением в скобках, используя оператор запятой.
f( (a, b) );
Я сделал поиск по проекту стандарта. В основном в грамматике -list
Производства - это те, которые имеют запятые в них для разделения различных элементов. Следующие результаты специфичны для C++03. В C++0x список выражений непосредственно делегируется списку инициализаторов, потому что в C++0x списки фигурных скобок также могут встречаться в аргументах функций и конструкторов.
- список выражений Для аргументов функции / конструктора (включая приведение функций)
- enumerator-list Список пунктов перечисления
init-декларатор-список Различные имена, объявленные в одной декларации
Пример:
int a, b;
- список объявлений параметров Список объявлений параметров (сюрприз!) функции
- список инициализатора Список, аналогичный списку выражений, но может включать в себя списки фигурных скобок. Используется для агрегатной инициализации (инициализация массивов или структур)
member-Declarator-list Аналогично списку объявлений init, но для объявлений членов в классах.
Пример:
struct A { int a, b; };
- base-specier-list Список базовых классов класса.
mem-initializer-list Список инициализаторов для членов
Пример:
struct A { A():a(0), b(0) { } int a; int b; };
- template-parameter-list Список объявлений параметров шаблона.
- template-arguments-list Список аргументов шаблона, переданных шаблону.
type-id-list Список типов для спецификаций исключений
Пример:
void f() throw(int, bool) { }
Существует также список идентификаторов для макропараметров, которых я не получил в этом списке, потому что это действительно часть грамматики препроцессора.
Использование токена запятой в качестве оператора отличается от его использования в вызовах и определениях функций, объявлениях переменных, объявлениях перечислений и подобных конструкциях, где он действует как разделитель.
Это связано с определением языка выражений, которое довольно сложно.
f(1, 2)
является выражением вызова функции с двумя параметрами. Наоборот, f((1, 2))
является выражением вызова функции с одним параметром, который является подвыражением 1, 2
, который оценит до 2.
Оператор запятой всегда действует как оператор запятой, но запятая не всегда означает оператор запятой - иногда это просто пунктуация.
Относительно того, когда это пунктуация, простой ответ - "когда стандарт говорит так". Прохождение всех ситуаций, когда стандарт говорит так, дает гораздо более длинный ответ, но вряд ли он будет намного более полезным, потому что (для одного примера) он должен иметь дело с множеством угловых случаев, которые большинству людей не безразличны. около.