Когда область полного класса действительно полезна в аргументах по умолчанию, инициализаторах членов по умолчанию и спецификации исключений? - PullRequest
2 голосов
/ 05 марта 2020

Стандарт говорит, что аргументы по умолчанию, инициализаторы по умолчанию для членов класса и спецификации исключений методов должны быть проанализированы в контексте полного класса; то есть класс должен рассматриваться как завершенный в этих выражениях или спецификаторах. Естественно, из этого следует, что все имена, определенные в области видимости класса, должны быть видны этим выражениям, даже имена, объявленные / определенные после выражения:

struct Test
{
    // Well-formed, `bar` is looked up in complete-class context:
    static void foo() noexcept(noexcept(bar()));

    static void bar() noexcept;
};

Я представляю, это требование налагает большую нагрузку на компиляторы: у них нет иного выбора, кроме как отложить анализ этих выражений до полного определения класса (или даже дальше, в случае вложенных классов), что приводит к другим проблемам и подводным камням.

Вот почему я не могу не задаться вопросом: Почему? Что хорошего в этом?
Разве не всегда возможно изменить порядок объявлений членов таким образом, чтобы имя всегда объявлялось до его использования ( до Я имею в виду поток исходного текста).

Не могли бы вы придумать пример, который не может быть переупорядочен, чтобы аргумент по умолчанию, инициализатор по умолчанию и спецификация исключения явно должны * анализироваться в 1017 * контекст полного класса?

1 Ответ

1 голос
/ 05 марта 2020

Пример счетчика:

struct Test
{
    // Well-formed, `bar` is looked up in complete-class context:
    static void foo() noexcept(noexcept(bar()));

    static decltype(foo()) bar() noexcept;
};

Возможно, это не реалистичный пример c (вместо этого я мог бы написать простоту void), но запрет такой взаимозависимости был бы основным ограничением, которое было бы ненужным, потому что компиляторы могут обрабатывать код, подобный приведенному выше.

Другой пример, который, возможно, больше отвечает на ваш вопрос:

struct Test
{
    // Well-formed, `bar` is looked up in complete-class context:
    static void foo() noexcept(noexcept(bar()));

    static void bar(decltype(foo) f = foo) noexcept;
};
...