non static variables in a namespace (in .h) ?

V

vthomasset

Hi,

Sorry for the bad subject, but i couldn't figure a better one.

I would like to understand why a variable declared non static in a
header causes multiple symbol definitions (if included in different
compilation units) while the same declaration in a namespace does not.

Also, what is the correct way to declare a scoped variable in a
header ? Using extern and declaring it in a separate compilation
unit ?

Thank you,
Vincent
 
J

John Ratliff

Hi,

Sorry for the bad subject, but i couldn't figure a better one.

I would like to understand why a variable declared non static in a
header causes multiple symbol definitions (if included in different
compilation units) while the same declaration in a namespace does not.

Could you show me an example, cause if you define a variable twice in
the same namespace, you should get multiple symbol definitions and
linker errors.

Did you mean you can define the same variable in different namespaces?
That's fine, of course.
Also, what is the correct way to declare a scoped variable in a
header ? Using extern and declaring it in a separate compilation
unit ?

If you have to put the definition in a namespace in a header included in
multiple compilation units, then you should declare it extern and define
it in a single compilation unit.

ex:

myhdr.hh

#ifndef MYHDR_HH_
#define MYHDR_HH_

namespace myns {
extern int myvar;
}

#endif

main.cc

#include "myhdr.hh"

int myns::myvar;

int main() {
myns::myvar = 6;
}

aux.cc

#include "myhdr.hh"

void myfcn() {
myns::myvar = 10;
}

--John Ratliff
 
V

Victor Bazarov

Sorry for the bad subject, but i couldn't figure a better one.

I would like to understand why a variable declared non static in a
header causes multiple symbol definitions (if included in different
compilation units) while the same declaration in a namespace does not.

I don't believe that the second part of this statement is correct.
Are you sure about "the same declaration"?

Anyway, an object that is not const and is not explicitly declared
'static' has _external_ linkage, IOW its name is visible from other
translation units. If you define (if the declaration does not have
'extern' specifier, it's a definition) objects with the same name
in more than one translation unit, it's a violation of the ODR. You
usually get the error from the linker who is the last to check the
ODR when linking different TUs together.

If you declare the object 'static', its name is hidden from other TU
(not extern), the term is that the name has _internal_ linkage. That
way you can have objects named the same in different TUs.
Also, what is the correct way to declare a scoped variable in a
header ?

"Scoped"? What does that mean? Any variable is scoped, IOW every
variable has its scope.
Using extern and declaring it in a separate compilation
unit ?

There are variations on the theme, but they all essentially lead to
the same: declaration is available in every TU, and the definition
exist only in one TU.

V
 
V

Victor Bazarov

John said:
Could you show me an example, cause if you define a variable twice in
the same namespace, you should get multiple symbol definitions and
linker errors.

Did you mean you can define the same variable in different namespaces?
That's fine, of course.

I just thought of what it could be: anonymous namespaces. But that
falls under "different" category, of course, only the OP didn't think
of it that way, most likely.

V
 
V

vthomasset

I don't believe that the second part of this statement is correct.
Are you sure about "the same declaration"?

My example comes from some software i use. In the main include file,
it declares a
bunch of strings as in the following:

namespace x {
const std::string s1 = "txt1";
const std::string s2 = "txt2";
}

and the software compiles and runs just fine. When i saw this it
struck as being strange (that it didn't cause link time error), so i
just added a simple test string declaration outside of the namespace
and, of course, got a bunch of 'redeclared symbol' messages at link
time.
Anyway, an object that is not const and is not explicitly declared
'static' has _external_ linkage, IOW its name is visible from other
translation units. If you define (if the declaration does not have
'extern' specifier, it's a definition) objects with the same name
in more than one translation unit, it's a violation of the ODR. You
usually get the error from the linker who is the last to check the
ODR when linking different TUs together.

These strings are const. Does it make any difference ?
"Scoped"? What does that mean? Any variable is scoped, IOW every
variable has its scope.

I meant in a namespace... sorry.
There are variations on the theme, but they all essentially lead to
the same: declaration is available in every TU, and the definition
exist only in one TU.

OK, so being in a namespace does not change the linkage type in any
way ?

Vincent
 
V

vthomasset

(e-mail address removed) wrote:
Could you show me an example, cause if you define a variable twice in
the same namespace, you should get multiple symbol definitions and
linker errors.

See my response to Victor Bazarow. I can give a link to the header
file on source control if you would like to see the real code, but
it's really as plain as i said (though the variables are const).
Did you mean you can define the same variable in different namespaces?
That's fine, of course.

No, i meant in the same namespace.
If you have to put the definition in a namespace in a header included in
multiple compilation units, then you should declare it extern and define
it in a single compilation unit.

<snip example code>

OK, this is how i understand it, so i don't understand why it works
correctly in this other software.

Vincent
 
V

Victor Bazarov

My example comes from some software i use. In the main include file,
it declares a
bunch of strings as in the following:

namespace x {
const std::string s1 = "txt1";
const std::string s2 = "txt2";
}

So, have you tried doing the same without the namespace? Does it
make an iota of difference (except for the s1 and s2 name lookup)?
and the software compiles and runs just fine. When i saw this it
struck as being strange (that it didn't cause link time error), so i
just added a simple test string declaration outside of the namespace
and, of course, got a bunch of 'redeclared symbol' messages at link
time.

Nothing strange. Objects are 'const', they have internal linkage.
These strings are const. Does it make any difference ?
Absodamnlutely.


I meant in a namespace... sorry.

Well, those that are "not in a namespace" are actually *in* the
_global_ namespace. The prefix for finding those is '::'. E.g.

int a = 0;
int main() {
double a = 3.14159;
return ::a; // note the ::
}

There are two 'a' objects here, one has global namespace scope,
the other has 'main' function scope.
OK, so being in a namespace does not change the linkage type in any
way ?

Nope.

V
 
V

vthomasset

and the software compiles and runs just fine. When i saw this it
struck as being strange (that it didn't cause link time error), so i
just added a simple test string declaration outside of the namespace
and, of course, got a bunch of 'redeclared symbol' messages at link
time.

Hmmm, sorry, i just realized that i declared a non const string
outside
the namespace (which caused the error). If declared const, i don't get
a linking error, so it appears my question is actually about the const
keyword rather than on being in a namespace.
 
V

Victor Bazarov

Hmmm, sorry, i just realized that i declared a non const string
outside
the namespace (which caused the error). If declared const, i don't get
a linking error, so it appears my question is actually about the const
keyword rather than on being in a namespace.

Yep. 'const' without "extern" gives the object internal linkage.

V
 
V

vthomasset

So, have you tried doing the same without the namespace? Does it
make an iota of difference (except for the s1 and s2 name lookup)?

I have now. :)
Nothing strange. Objects are 'const', they have internal linkage.

Thanks a lot for your explanations.

Vincent
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top