2017-01-18 25 views
7

При чтении этой части С ++ (14): a free draft N4141, closest to C++14Локальные правила класса выровнены с выводом типа с ++ 14?

9.8 деклараций локального класса [class.local]

[..] Имя локального класса является локальным для его ограждающих объем. [..]

Декларации в локальном классе не должны использовать odr-use (3.2) переменную с продолжительностью автоматического хранения из охватывающей области. [Пример:

//[..] 
void f() 
{ 
    static int s ; 
    int x; 
    // [..] 
    struct local { 
     int g() { return x; } // error: odr-use of automatic variable x 
     int h() { return s; } // OK 
     // [..] 
    }; 
} 
local* p = 0; // error: local not in scope 

-end пример]

Я заметил, что, во-первых - я могу определить p с возвращаемого значения автоматического удержания:

auto f() 
{ 
    static int s; 
    int x; 
    struct local 
    { 
    int h() { return s; } 
    }; 
    return local{}; 
} 
decltype(f())* p = 0; // OK - ignored, that local is not in scope! 

Может быть, это, кажется, хорошо, почему не использовать локальный тип, выведя его из возвращаемого значения функции, но - кажется, таким образом я могу получить доступ к локальной переменной s до ее построения:

struct TalkativeInt 
{ 
    TalkativeInt() : value() 
    { 
     std::cout << "TalkativeInt()\n"; 
    } 
    TalkativeInt(int value) : value(value) 
    { 
     std::cout << "TalkativeInt(" << value << ")\n"; 
    } 

    int value; 
}; 

auto f() 
{ 
    static TalkativeInt s = 7; 
    int x; 
    struct local 
    { 
    auto h() { return s.value; } 
    }; 
    return local{}; 
} 
decltype(f())* p = 0; 

int main() { 
    decltype(f()) l; 
    std::cout << l.h(); 
} 

Выход только ::

0 

Но можно было бы ожидать:

TalkativeInt(7) 
7 

Оба лязг и НКУ не протестуют каким-либо образом, см demo.

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

9.8 деклараций местного класса [class.local]

или в

7.1.6.4 авто спецификатором [dcl.spec.auto]

?

Конечно, я считаю, что чтение (и запись) из переменной перед ее построением плохой предмет, но я ничего не нашел об этом в стандарте - возможно, это было невозможно до C++ 14? Или есть некоторые основные правила, которые я просто забыл?

+2

Ой, это противно. Это похоже на лазейку и, вероятно, вызывает неопределенное поведение ... – Quentin

+1

Хмм. «Локальные объявления класса» говорят только о том, что имя не видно снаружи. Это не обязательно означает, что тип не может использоваться снаружи, как я его вижу. Я не совсем уверен, как вы могли бы использовать такую ​​функцию pre-C++ 11, поскольку вы не могли даже объявить ее локальным. Но, возможно, я просто пропущу точку здесь. –

+1

В §9.8 говорится только, что _name_ является локальным. Не совсем то, что вы можете использовать сущность без указания ее имени. – cpplearner

ответ

8

Правило для статических локальных переменных plain and simple:

Динамическая инициализация переменной блок-области действия со статической продолжительностью хранения (3.7.1) или продолжительности хранения нити (3.7.2) выполняется первый контроль времени проходит через его объявление; такая переменная считается инициализированной после завершения ее инициализации.

И доступ к объектам объекта до его строительства запрещен [basic.life]/(7.1).

+0

Я предполагаю, что вы имеете в виду доступ к 'f() :: s.value' в моем вопросе неправильно, я считаю, что вызов' main(): lh() 'будет действителен, если реализация этой функции не коснется' f() :: s'? – PiotrNycz

+1

@PiotrNycz Правильно. – Columbo