7

My simple code looks like:

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;

Is this code good with standard or no ? Visual Studio compiles it without errors but the Intel C++ compiler says: unresolved external symbol "int asd::i" (?i@asd@@3HA)

For more fun if i change b.cpp to:

namespace asd
{
    int i = 4;
}

Then Visual Studio C++ 2013 says: unresolved external symbol "int i" (?i@@3HA)

But the Intel C++ compiler says ok :) What is the proper version of this code If I want to have this extern in class member function (is it legal ?) ?

Edit: The best results are, when we change b.cpp to:

namespace asd
{
    int i = 4;
}
int i = 5;

Visual c++ prints 5, intel compiler 4 :)

AdamF
  • 2,501
  • 17
  • 30

2 Answers2

3

It is legal to declare an extern or a static variable inside any function. Your fix of the b.cpp where you put namespace around the definition of that extern is the right fix, too.

Visual Studio C++ 2013 complains about a name outside the asd namespace (check the demangler to see what these extra characters around the name i represent). This is incorrect, because the declaration places i into the namespace asd.

C++ standard illustrates this in section 3.5.7. It is using an extern function as an example, but it illustrates the rule of placement of the name in the enclosing namespace.

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

The comments on lines 4, 9, and 11 show that the name declared with extern inside the member function needs to be placed in the enclosing namespace. It is a good, self-contained test case illustrating a bug in Microsoft's compiler.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Looks like Visual Studio is wrong.

This is what I found in the draft standard:

3.3.2/10

Function declarations at block scope and variable declarations with the extern specifier at block scope refer to declarations that are members of an enclosing namespace, but they do not introduce new names into that scope.

Having said that, I would move the extern declaration out of the function and into the namespace to see if that makes any difference.

namespace asd
{
    extern int i;
    class B
    {
    public:
        void ss()
        {
            std::cout << i;
        }
    };
}
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270