#c #visual-studio-2013 #icc
# #c #visual-studio-2013 #icc
Вопрос:
Мой простой код выглядит так:
a.cpp:
#include <iostream>
namespace asd
{
class B
{
public:
void ss()
{
extern int i;
std::cout << i;
}
};
}
int main()
{
asd::B e;
e.ss();
}
b.cpp:
int i = 4;
Подходит ли этот код для стандарта или нет?
Visual Studio компилирует его без ошибок, но компилятор Intel C говорит:
неразрешенный внешний символ «int asd::i» (?i@asd@@3HA)
Для большего удовольствия, если я изменю b.cpp чтобы:
namespace asd
{
int i = 4;
}
Затем Visual Studio C 2013 говорит:
неразрешенный внешний символ «int i» (?i @@3HA)
Но компилятор Intel C говорит, что все в порядке 🙂 Какова правильная версия этого кода, если я хочу иметь эту внешнюю функцию в функции-члене класса (это законно?)?
Редактировать: наилучшие результаты, когда мы меняем b.cpp чтобы:
namespace asd
{
int i = 4;
}
int i = 5;
Visual c печатает 5, компилятор intel 4 🙂
Комментарии:
1. Что это за таинственный «другой компилятор»?
2. Я сравнил результаты с компилятором Intel. Gcc я не тестировал.
3. Пожалуйста, покажите свой B.cpp , он компилируется с помощью gcc для меня.
4. Пока области пространства имен для определения и объявления совпадают, все должно работать. Смотрите ответ @dasblinkenlight
5. Хорошо, я сообщил об ошибке: connect.microsoft.com/VisualStudio/feedback/details/909772 /…
Ответ №1:
Законно объявлять extern
или static
переменную внутри любой функции. Ваше исправление b.cpp
того, где вы помещаете пространство имен вокруг определения этого extern
, тоже является правильным исправлением.
Visual Studio C 2013 жалуется на имя вне asd
пространства имен (проверьте деманглер, чтобы увидеть, что представляют эти дополнительные символы вокруг имени i
). Это неверно, потому что объявление помещается i
в пространство asd
имен .
Стандарт C иллюстрирует это в разделе 3.5.7. Он использует extern
функцию в качестве примера, но он иллюстрирует правило размещения имени во вложенном пространстве имен.
namespace X {
void p() {
q(); // error: q not yet declared
extern void q(); // q is a member of namespace X
}
void middle() {
q(); // error: q not yet declared
}
void q() { /* ... */ } // definition of X::q
}
void q() { /* ... */ } // some other, unrelated q
Комментарии к строкам 4, 9 и 11 показывают, что имя, объявленное extern
внутри функции-члена, должно быть помещено во включающее пространство имен. Это хороший, автономный тестовый пример, иллюстрирующий ошибку в компиляторе Microsoft.
Ответ №2:
Похоже, Visual Studio ошибается.
Это то, что я нашел в проекте стандарта:
3.3.2/10
Объявления функций в области блока и объявления переменных со
extern
спецификатором в области блока относятся к объявлениям, которые являются членами окружающего пространства имен, но они не вводят новые имена в эту область.
Сказав это, я бы переместил extern
объявление из функции в пространство имен, чтобы посмотреть, имеет ли это какое-либо значение.
namespace asd
{
extern int i;
class B
{
public:
void ss()
{
std::cout << i;
}
};
}