Почему операторы не могут появляться в области имен? - PullRequest
2 голосов
/ 12 декабря 2011

Любая идея о том, какое правило в стандарте гласит такие утверждения:

p++; //where 'p' is pointer to array

не может появиться в глобальной области видимости?

Я ищу ссылку, а не просто объяснение, если это возможно.

Ответы [ 3 ]

12 голосов
/ 12 декабря 2011

Выражение p++, которое вы написали, находится в области имен. Это запрещено грамматикой тела-пространства имен , которое определено в §7.3.1 / 1 как:

Пространство имен тела:
Заявление-сл неавтоматического

, который говорит, что тело пространства имен может опционально содержать только объявление . И p++, безусловно, не декларация, это выражение, поэтому Стандарт неявно запрещает это. Стандарт может иметь явное заявление, запрещающее это, но я думаю, что вышесказанного должно быть достаточно.

Таким же образом, вы не можете сделать это:

namespace sample
{
  f(10,10); //error
  std::cout << "hello world" << std::endl;//error
}

Но если вы каким-то образом конвертируете выражений в объявлений (точнее используйте выражений в объявлениях), то вы можете оценить так называемые выражения. Вот одна хитрость:

#include<iostream>

namespace sample
{
  struct any { template<typename T> any(const T&){} };

  void f(int a,int b) { std::cout << a * b <<  std::endl; }

  any a1= (f(10,10), 0); //ok
  any a2 = std::cout << "hello world" << std::endl;//ok
}

int main() {}

Вывод (если вам повезет):

100
hello world

Онлайн демо: http://ideone.com/icbhh

Обратите внимание, что тип возвращаемого значения f() равен void, что означает, что я не могу написать следующее ( см. Ошибку) :

any a1 = f(10,10); //error

Именно поэтому я использовал оператор запятая , чтобы выражение могло иметь некоторое значение, которое вычисляется до последнего операнда в выражении запятой. В случае std:cout, поскольку он возвращает std::ostream&, мне не нужно использовать оператор запятой; без него все нормально.

Еще одна интересная вещь в приведенном выше коде: почему я определил any и шаблонный конструктор в нем? Ответ таков: я написал это так, чтобы можно было присвоить значение любому типу (без каламбура), будь то int, std::ostream& или что-то еще. Конструктор templated может принимать аргументы любого типа.

Но не пишите такой код. Они не гарантированно работают так, как вы ожидаете.

Прочтите ответы в этой теме, чтобы узнать, почему такое кодирование может быть опасным:

0 голосов
/ 12 декабря 2011

ВЫБЕРИТЕ «Язык программирования C ++», конечно же, Страуструпом.

В разделе r.6.1 говорится об операторах - которые могут быть метками, выражениями, составными операторами, операторами выбора, операторами итерации, операторами перехода или объявлениемзаявления.

Затем вернитесь к разделу 3.3.1, в котором показан синтаксис оператора и ссылки: Обратите внимание, что ..... нет оператора присваивания или оператора вызова процедуры.Присвоение и вызов функции обрабатываются как выражения.

Затем в разделе r.3.1 говорится о четырех типах области действия - локальной, функции, файла и класса.Так как глобальный по сути это «файловый» охват.Имена допускаются в глобальной области видимости, так же как и классы, впервые объявленные в типе возвращаемого значения или аргумента.

Действительно, не может быть найдено никакого конкретного определителя, который выводит состояния, которые не могут быть в выражении-выражении в глобальной области видимости, но пропускаяссылки показывают, что вы можете иметь.

0 голосов
/ 12 декабря 2011

Говоря «подобные заявления», я полагаю, вы знаете, что / почему заявления в целом не могут быть в глобальном масштабе.

p++;

Это утверждение, потому что оно в основном переводится на:

p = p + 1;

Что является нормальным утверждением.

...