У меня возникли некоторые трудности с пониманием [basic.scope.pdecl] / 7 - PullRequest
6 голосов
/ 18 марта 2019

[basic.scope.pdecl] / 7

Точка объявления класса first , объявленная в уточненный спецификатор типа выглядит следующим образом:

(7.1) для декларации вида

ключ класса атрибут-спецификатор-секв опт идентификатор ;

идентификатор объявляется как имя класса в области действия, содержащей объявление, в противном случае

(7.2) для уточненного спецификатора типа вида

ключ класса идентификатор

, если подробный спецификатор типа используется в decl-specier-seq или
параметр-объявление-предложение функции, определенной в пространстве имен область действия, идентификатор объявлен как имя класса в пространстве имен который содержит декларацию; иначе, кроме как друг При объявлении идентификатор объявляется в наименьшем пространстве имен или блок область действия, содержащая объявление. [Примечание: эти правила также применять в шаблонах. - конец примечание] [Примечание: другие формы подробный спецификатор типа не объявляет новое имя, и поэтому должен ссылаться на существующее имя типа . Смотрите [basic.lookup.elab] и [Dcl.type.elab]. - конец примечания]

Рассмотрим приведенный выше случай (7.2), в котором подробный спецификатор типа используется в decl-specier-seq параметра-объявления-предложения функции, определенной в области имен. Как это согласуется с тем фактом, что этот уточненный спецификатор типа должен быть first объявлением класса в его пространстве имен?

Рассмотрим пример ( demo ) ниже:

Файл prog.cc:

struct S;
extern S s;
int S;
void f(struct S&);     // The elaborated-type-specififer `struct S` is not
                       // the first declaration in the global namespace and
                       // if we eliminate the first declaration `struct S;` 
                       // on the top, the code doesn't compile !!
int main(){
    f(s);
}

Файл other.cc:

#include<iostream>
struct S{
    int i = 1;
};
void f(struct S& s) { std::cout << s.i << '\n'; }
S s;

Обратите внимание, что приведенный выше код компилируется и выполняется правильно, но подробный спецификатор типа в объявлении параметра функции f не первый в глобальное пространство имен.

Предполагая, что моя интерпретация относительно [basic.scope.pdecl] / 7 верна, я хотел бы увидеть пример, демонстрирующий применение пункта (7.2) выше, где указанная декларация будет first в своем пространстве имен.

Ответы [ 2 ]

4 голосов
/ 19 марта 2019

если мы исключим первое объявление struct S; сверху, код не скомпилируется !!

Ну, это потому, что вам все равно нужно объявить имя, прежде чем использовать его.

int S;
void f(struct S&); 
extern struct S s; // If you write this line before then it
                   // will not compile.
                   // The name still needs to be declared
                   // before you use it.
// If you drop the `int S` above, then the following
// will also compile, since S has already been declared
// extern S s2;

int main(){
    f(s);
}

Обратите внимание, что приведенный выше код компилируется и выполняется правильно, но подробный спецификатор типа в объявлении параметра Функция f не первая в глобальном пространстве имен.

Я не понимаю, что вы пытаетесь здесь сказать.Поскольку это не первое, имя не объявляется и [basic.scope.pdecl] p7 не применяется.

Я хотел бы увидеть пример, демонстрирующий применение пункта (7.2) выше,где упомянутое объявление будет первым в своем пространстве имен.

auto addrof(struct S& s) { // First declaration
    return &s;
}
int get(struct T&); // First declaration
3 голосов
/ 18 марта 2019

Я хотел бы увидеть пример, демонстрирующий применение пункта (7.2) выше, где упомянутое объявление будет первым в его пространстве имен.

Просто:

namespace ns {
    // declares S into ns as per [basic.scope.pdecl]
    void f(struct S&);
}

extern ns::S s;
//extern ::S s; // not declared

Здесь struct S сначала объявляется в подробном спецификаторе типа в условии объявления параметров функции, определенной в области имен, в форме class-key identifier и, следовательно, [basic.scope.pdecl]Применяется /7.2 и struct S объявляется в пространстве имен ns, в котором объявлена ​​функция.

вам придется использовать объект класса S в вашей функции f

Вот пример :

// ... continuing from previous example ...
namespace ns {
    struct S {
        int i;
    };

    void f(S& s) {
        std::cout << s.i;
    }
}

В качестве бонуса, пример, где класс не был впервые объявлен в сложномспецификатор, и поэтому указанное в кавычках правило не применимо:

struct S;
namespace ns {
    void f(struct S&); // refers to ::S
}

//extern ns::S s; // not declared
extern ::S s;

Здесь разработанный описатель типа не является первым объявлением struct S, поэтому [basic.scope.pdecl] / 7 не применяетсяприменить, и класс не объявляется в пространство имен.

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