Подтвердить что ты не робот

Структура С++, объявленная в функции, видимая в основном

Почему этот код работает? с c++14

// Example program
#include <iostream>
#include <string>
using namespace std;


auto fun()
{
    struct a
    {
        int num = 10;
        a()
        {

            cout << "a made\n";
        }
        ~a()
        {
            cout << "a destroyed\n";
        }
    };
    static a a_obj;
    return a_obj;
}


int main()
{
    auto x = fun();
    cout << x.num << endl;

}

Как выглядит вид a в главном? если я изменяю auto x= на a x=, он явно не компилируется, но как основные знают о типе a?

Объявление static существует, так как я пытался проверить что-то еще, но затем я наткнулся на это поведение.

Запуск здесь: https://wandbox.org/permlink/rEZipLVpcZt7zm4j

4b9b3361

Ответ 1

Это все удивительно, пока вы не осознаете это: имя видимость не скрывает тип. Он просто скрывает имя этого типа. Как только вы это понимаете, все имеет смысл.

Я могу показать вам это без auto, с просто старыми шаблонами:

auto fun()
{
    struct Hidden { int a; };

    return Hidden{24};
}

template <class T> auto fun2(T param)
{
    cout << param.a << endl; // OK
} 

auto test()
{
    fun2(fun()); // OK
}

Если вы посмотрите внимательно, вы увидите, что это та же ситуация, что и ваша:

у вас есть struct Hidden, который является локальным для fun. Затем вы используете объект типа Hidden внутри test: вы вызываете fun, который возвращает объект Hidden obj, а затем вы передаете этот объект в fun2, который, в свою очередь, не имеет проблемы, чтобы использовать объект Hidden во всем славе.

поскольку @Barry предположил, что то же самое происходит, когда вы возвращаете экземпляр частного типа из класса. Таким образом, мы имеем такое поведение с С++ 03. Вы можете попробовать сами.

Ответ 2

С++ 14 становится все более толерантным с auto. Ваш вопрос непонятен, потому что вы не заявляете, в чем проблема.

Теперь давайте рассмотрим ваш вопрос по-другому: почему он не работает с a x = ...?

Причина в том, что определение структуры не входит в объем основного. Теперь это сработает:

// Example program
#include <iostream>
#include <string>
using namespace std;

struct a
{
    int num = 10;
};

auto fun()
{
    static a a_obj;
    return a_obj;
}


int main()
{
    a x = fun();
    cout << x.num << endl;

}

Теперь здесь неважно, используете ли вы a или auto, потому что a отображается для main(). Теперь auto - это совсем другая история. Компилятор спрашивает: есть ли у меня достаточно информации для вывода (однозначно), что такое тип x? И ответ "да", потому что нет альтернативы a.