Неопределенная ссылка на статическую локальную переменную - PullRequest
9 голосов
/ 29 декабря 2011

Это самый простой пример, который я мог бы привести, который воспроизводит проблему.

template<class T>
struct X
{
    static void foo()
    {
        static int z = 0;
        []{ z = 1; }();
    }
};

int main()
{
    X<int>::foo();
    return 0;
}

Я пробовал это с MinGW 4.6 и 4.7, также с g ++ 4.6 в Ubuntu, и все они дают мне ошибку ссылки "неопределенная ссылка на` z '". Так что теперь это заставляет меня задуматься, если это даже законно. У VC10 с этим нет проблем.

Работает, если X - обычный класс вместо шаблона. Кроме того, я не думаю, что это связано с лямбдами, потому что я получаю сообщение об ошибке, даже если я заменяю лямбда на локальный класс.

Ответы [ 2 ]

10 голосов
/ 29 декабря 2011

g ++ принимает следующее, а VC ++ - нет:

[&z]{ z = 1; }();

Здесь z фиксируется, поэтому g ++ не жалуется на неопределенную ссылку . Тем не менее:

5.1.2 / 10:

Идентификаторы в списке захвата ищутся с использованием обычных правил для поиска безоговорочного имени (3.4.1); каждый такой поиск найдет переменная с автоматической продолжительностью хранения, объявленной в достижении область действия локального лямбда-выражения.

z - это , а не автоматическое хранение. Поэтому z не может быть захвачено. Поэтому поведение g ++ некорректно, а VC ++ корректен.

В вашем коде VC ++ принимает, а g ++ нет:

[]{ z = 1; }();

z доступен VC ++ как статическое хранилище, которое разрешено в лямбда-теле. g ++, по-видимому, не разрешает имя z в статической переменной, объявленной выше, и поэтому выдает неопределенную ссылку , в то время как это не должно.

ТЛ; др Это, вероятно, ошибка в g ++

Edit: Это действительно ошибка , исправленная в 4.7.

0 голосов
/ 29 декабря 2011

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

static void foo()
{
    static int z = 0;
    [&z]{ z = 1; }(); // Note: [&z]
}

В Википедии есть больше информации здесь .

...