Требуется ли для определения конструктора пространства имен область с указанием класса? - PullRequest
13 голосов
/ 19 августа 2011

Вот кое-что, чему мы все научились в 1-й день С ++, которое мы считаем само собой разумеющимся, но явно не следует из формулировок Стандарта.

Учитывая класс S, мы можем определить его конструктор

struct S { S(); };
S::S() { … }

Но Стандарт, похоже, также допускает это:

struct S { S(); };
S() { … }

Квалификация имени класса с самим собой всегда разрешена, но всегда избыточна. Например, S::S::S::S() { … } также является допустимым объявлением. Если S::S есть, то почему не просто S?

Из C ++ 11 §12.1 / 1,

Конструкторы не имеют имен. Специальный синтаксис объявления используется для объявления или определения конструктора. Синтаксис использует:

- необязательный decl-specier-seq, в котором каждый decl-спецификатор является либо спецификатором функции, либо constexpr,

- имя класса конструктора и

- список параметров

в таком порядке.

Это в равной степени относится к области класса или пространства имен. Существует специальное правило относительно области имен, §9.3 / 5,

Если определение функции-члена лексически выходит за пределы определения класса, имя функции-члена должно быть уточнено по имени класса с помощью оператора ::.

Однако конструкторы не имеют имен , так что это не относится, верно? Более того, нет причин требовать квалификации, потому что нет синтаксической двусмысленности. Функция, объявленная без возвращаемого типа и имени класса для идентификатора, всегда является синтаксической ошибкой в ​​соответствии с текущими правилами. Правильно?

Не то, чтобы мы начинали писать код с опущенной квалификацией, но есть ли причина, по которой ни один компилятор не принимает это, или это просто традиция?

Ответы [ 2 ]

3 голосов
/ 19 августа 2011

Да, это говорит о том,

Если определение функции-члена лексически выходит за пределы определения класса имя функции-члена должно быть квалифицировано по имени класса с помощью оператора ::.

Но не говорит, что функция-член без имени должна не быть квалифицированной по имени класса. Является ли? ;)

Это, кажется, приводит к неопределенной области в зависимости от реализаций. Однако форма A :: A определяется Стандартом.

5.1 Первичные выражения

Если используется имя-класса :: имя-класса, а два имени класса относятся к одному и тому же классу, эта нотация именует конструктор ..

Относительно того, разрешено ли A(){..} или нет, я думаю, что нет никаких оснований делать это условно (есть ли ЛЮБОЙ компилятор C ++, позволяющий это ?? AFAIK, нет):

  1. Поскольку конструктор - это специальная функция-член, способ A::A(){..} более согласуется с другими функциями-членами. Почему братья позволяют ему вести себя особенно? Это, вероятно, не стоит усилий.

  2. Никто не хочет рисковать написанием несовместимого кода, который явно не указан в Стандарте.

1 голос
/ 19 августа 2011

Столкнувшись с токенами S() { } в области имен, компилятор не может волшебным образом решить, что это ctor.По какому правилу грамматики получается такая последовательность токенов?Давайте игнорировать все, кроме определения функций;они не могут произвести часть ( ){ }.

Это означает, что S() должен быть декларатором , а decl-specier-seq opt должен быть пустым (см. §8.4.1).Впоследствии §9.2 / 7 сообщает нам, что объявитель должен назвать конструктор, деструктор или функцию преобразования.Но S тоже не называет.Следовательно, S() { } недопустимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...