473,394 Members | 1,699 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

question on c++ constants?

Dear All,

I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?

Thanks for your help!

Shuisheng
Oct 14 '08 #1
54 3526
shuisheng wrote:
I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?
Yes, we use them too. What's the problem?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 14 '08 #2
shuisheng wrote:
Dear All,

I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?

Thanks for your help!

Shuisheng


1. The easiest constants in classes are made by using enums:
#include <vector>

class SomeClass
{
enum { SIZE= 7 };

int array[SIZE];

std::vector<intintVector;
public:
SomeClass(): intVector(5) {}
};

2. Regarding global constants and the header file you mentioned, in
simple words:

You can #include the header file with the global constant only in one
"implementation" file (e.g. .cpp) and to the rest implementation files
(e.g. .cpp), you can add the declaration:
extern const double PI;
==In general avoid objects in the global namespace.

3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).
file1.cpp:
E.g. pi.h:

namespace SomeNamespace
{
const double PI = 3.14;
}


What should be preferred instead of constants in the global namespace:

Constants (consts/enums) in anonymous namespaces (= local file scope
only), and constants (consts/enums) in named namespaces.
Regarding classes, you can either use static constants or (usually
better) enums.
Oct 14 '08 #3
Corrected:

shuisheng wrote:
Dear All,

I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?

Thanks for your help!

Shuisheng

1. The easiest constants in classes are made by using enums:
#include <vector>

class SomeClass
{
enum { SIZE= 7 };

int array[SIZE];

std::vector<intintVector;
public:
SomeClass(): intVector(SIZE) {}
};

2. Regarding global constants and the header file you mentioned, in
simple words:

You can #include the header file with the global constant only in one
"implementation" file (e.g. .cpp) and to the rest implementation files
(e.g. .cpp), you can add the declaration:
extern const double PI;
==In general avoid objects in the global namespace.

3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).
file1.cpp:
E.g. pi.h:

namespace SomeNamespace
{
const double PI = 3.14;
}


What should be preferred instead of constants in the global namespace:

Constants (consts/enums) in anonymous namespaces (= local file scope
only), and constants (consts/enums) in named namespaces.
Regarding classes, you can either use static constants or (usually
better) enums.

Oct 14 '08 #4
Ioannis Vranos wrote:
Corrected:
[..]

Regarding classes, you can either use static constants or (usually
better) enums.
Well, there aren't double or string enums, so... The difference between
the class [non-integral] constants and the namespace ones is that the
class constants have to be declared in the class and *defined* in some
translation unit, while the namespace constants can be defined in the
header (which means they will be duplicated in every translation unit
that includes the header), which is OK because they have internal
linkage (unless you specify otherwise).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 14 '08 #5
On Oct 14, 1:20*pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
Ioannis Vranos wrote:
Corrected:
[..]
Regarding classes, you can either use static constants or (usually
better) enums.

Well, there aren't double or string enums, so... *The difference between
the class [non-integral] constants and the namespace ones is that the
class constants have to be declared in the class and *defined* in some
translation unit, while the namespace constants can be defined in the
header (which means they will be duplicated in every translation unit
that includes the header), which is OK because they have internal
linkage (unless you specify otherwise).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
So I think the following is the right way, please confirm it. I use PI
as an example.

For global constants:

// in constants.h
const double PI = 3.14;

// in h or cpp files to use PI
#include "constants.h"
double a = PI;
For constants in namespace:

// in constants.h
namespace constants
{
const double PI = 3.14;
};

// in h or cpp files to use PI
#include "constants.h"
double d = constants::PI;
For constants in classes:

// in class.h
class A
{
public:
static const double PI;
};

// in class.cpp
const double A::PI = 3.14;

// in h and cpp files to use it.
#include "class.h"
double a = A::PI;

And I think Ioannis Vranos's way to define global constants will bring
about problems as shown in http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

Thanks and best regards,
Oct 14 '08 #6
shuisheng wrote:
[..]
So I think the following is the right way, please confirm it. I use PI
as an example.

For global constants:

// in constants.h
const double PI = 3.14;

// in h or cpp files to use PI
#include "constants.h"
double a = PI;
For constants in namespace:

// in constants.h
namespace constants
{
const double PI = 3.14;
};

// in h or cpp files to use PI
#include "constants.h"
double d = constants::PI;
For constants in classes:

// in class.h
class A
{
public:
static const double PI;
};

// in class.cpp
const double A::PI = 3.14;

// in h and cpp files to use it.
#include "class.h"
double a = A::PI;

And I think Ioannis Vranos's way to define global constants will bring
about problems as shown in http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx
The code you showed here is perfectly fine, and you can declare/define
any constants that way, not just of fundamental types, AFAIC.

The contents of the web page you cited do bother me. I am not sure what
"static linkage" is; there is no such term in C++ Standard. Why would
the page say that "If you try to use a global constant in C++ in
multiple files you get an unresolved external error"? What kind of
nonsense is that? If you *do* declare some object "extern", then you
must define it somewhere. If you don't defined it, you violate the ODR.

The point in using constants like you've shown is that there *is* a
*defined* object in every module, it has internal linkage (since it's
declared 'const' and does not have external linkage), and that's it.
Whether those objects are "optimized out" does not matter. From the
language point of view they exist, have value, are constant, and that's
about all we need to know.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 14 '08 #7
On Oct 14, 4:58*pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
shuisheng wrote:
[..]
So I think the following is the right way, please confirm it. I use PI
as an example.
For global constants:
* // in constants.h
* const double PI = 3.14;
* // in h or cpp files to use PI
* #include "constants.h"
* double a = PI;
For constants in namespace:
* // in constants.h
* namespace constants
* {
* * const double PI = 3.14;
* };
* // in h or cpp files to use PI
* #include "constants.h"
* double d = constants::PI;
For constants in classes:
* // in class.h
* class A
* {
* public:
* * static const double PI;
* };
* // in class.cpp
* const double A::PI = 3.14;
* // in h and cpp files to use it.
* #include "class.h"
* double a = A::PI;
And I think Ioannis Vranos's way to define global constants will bring
about problems as shown inhttp://msdn.microsoft.com/en-us/library/0d45ty2d(VS.80).aspx

The code you showed here is perfectly fine, and you can declare/define
any constants that way, not just of fundamental types, AFAIC.

The contents of the web page you cited do bother me. *I am not sure what
"static linkage" is; there is no such term in C++ Standard. *Why would
the page say that "If you try to use a global constant in C++ in
multiple files you get an unresolved external error"? *What kind of
nonsense is that? *If you *do* declare some object "extern", then you
must define it somewhere. *If you don't defined it, you violate the ODR..

The point in using constants like you've shown is that there *is* a
*defined* object in every module, it has internal linkage (since it's
declared 'const' and does not have external linkage), and that's it.
Whether those objects are "optimized out" does not matter. *From the
language point of view they exist, have value, are constant, and that's
about all we need to know.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
I tested using "extern" as following in visual studio 2005.

//! in constants.h
extern const double PI;

//! in constants.cpp
const double PI = 3.14;

When using for multiple files, especially when PI is defined in a
library, it gives a link error. I think C++ treats global constants
different from global non-constant variables. My understanding is
that: there is no external objects somewhere for global constants,
even in "constants.cpp" having the code "const double PI = 3.14;".
Oct 14 '08 #8
shuisheng wrote:
>
So I think the following is the right way, please confirm it. I use PI
as an example.

For global constants:

// in constants.h
const double PI = 3.14;

// in h or cpp files to use PI
#include "constants.h"
double a = PI;

This is OK, but try not polluting the global namespace.
>
For constants in namespace:

// in constants.h
namespace constants
{
const double PI = 3.14;
};

// in h or cpp files to use PI
#include "constants.h"
double d = constants::PI;

There are also the anonymous namespaces which have local file scope:
namespace
{
const double PI= 3.14;
};
For constants in classes:

// in class.h
class A
{
public:
static const double PI;
};

// in class.cpp
const double A::PI = 3.14;

// in h and cpp files to use it.
#include "class.h"
double a = A::PI;

or enums for integer constants.
And I think Ioannis Vranos's way to define global constants will bring
about problems as shown in http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

Yes you are right. This is one of the differences between C++ and C.

Victor check TC++PL3 on page 200.
const int x= 7; in global scope is equivalent to

static const int x= 7;
For this to work as C, definition must be accompanied with the word
extern, that is:
extern const double PI= 3.14;
But as I said, we must avoid global variables as much as possible and
must avoid polluting the global namespace as much as possible.
Oct 14 '08 #9
Recorrected:
shuisheng wrote:
Dear All,

I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?

Thanks for your help!

Shuisheng

Corrected:

shuisheng wrote:
Dear All,

I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?

Thanks for your help!

Shuisheng

1. The easiest constants in classes are made by using enums:
#include <vector>

class SomeClass
{
enum { SIZE= 7 };

int array[SIZE];

std::vector<intintVector;
public:
SomeClass(): intVector(SIZE) {}
};

2. Regarding global constants and the header file you mentioned, in
simple words:

i) You can #include the header file (e.g .h) in all implementation files
(e.g. .cpp), keeping in mind that as a result, each instance of the
constant (defined as const double PI= 3.14;) is a different file-scope
(more accurately, compilation unit - scope) object.
ii) You can #include the header file with the global constant in the form:
extern const double PI= 3.14;
in one "implementation" file (e.g. .cpp) and to the rest implementation
files (e.g. .cpp), you can add the declaration:
extern const double PI;


==In general avoid objects in the global namespace.

3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).
E.g. pi.h:

namespace SomeNamespace
{
const double PI = 3.14;
}


What should be preferred instead of constants in the global namespace:

Constants (consts/enums) in anonymous namespaces (= local file scope
only), and constants (consts/enums) in named namespaces.
Regarding classes, you can either use static constants or (usually
better) enums.
Oct 14 '08 #10
shuisheng wrote:
On Oct 14, 4:58 pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
>shuisheng wrote:
>>[..]
So I think the following is the right way, please confirm it. I use PI
as an example.
For global constants:
// in constants.h
const double PI = 3.14;
// in h or cpp files to use PI
#include "constants.h"
double a = PI;
For constants in namespace:
// in constants.h
namespace constants
{
const double PI = 3.14;
};
// in h or cpp files to use PI
#include "constants.h"
double d = constants::PI;
For constants in classes:
// in class.h
class A
{
public:
static const double PI;
};
// in class.cpp
const double A::PI = 3.14;
// in h and cpp files to use it.
#include "class.h"
double a = A::PI;
And I think Ioannis Vranos's way to define global constants will bring
about problems as shown inhttp://msdn.microsoft.com/en-us/library/0d45ty2d(VS.80).aspx
The code you showed here is perfectly fine, and you can declare/define
any constants that way, not just of fundamental types, AFAIC.

The contents of the web page you cited do bother me. I am not sure what
"static linkage" is; there is no such term in C++ Standard. Why would
the page say that "If you try to use a global constant in C++ in
multiple files you get an unresolved external error"? What kind of
nonsense is that? If you *do* declare some object "extern", then you
must define it somewhere. If you don't defined it, you violate the ODR.

The point in using constants like you've shown is that there *is* a
*defined* object in every module, it has internal linkage (since it's
declared 'const' and does not have external linkage), and that's it.
Whether those objects are "optimized out" does not matter. From the
language point of view they exist, have value, are constant, and that's
about all we need to know.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

I tested using "extern" as following in visual studio 2005.

//! in constants.h
extern const double PI;

//! in constants.cpp
const double PI = 3.14;
This 'PI' and the 'PI' you declared in the header are two different pies
(so to speak). One has external linkage because you told it to have it
by using 'extern', the other has internal linkage because you declared
it 'const' and didn't specify any linkage and by default it's internal.

The fix for that is

//! in constants.cpp
extern const double PI = 3.14;

or

//! in constants.cpp
#include "constants.h"
const double PI = 3.14;
When using for multiple files, especially when PI is defined in a
library, it gives a link error. I think C++ treats global constants
different from global non-constant variables. My understanding is
that: there is no external objects somewhere for global constants,
even in "constants.cpp" having the code "const double PI = 3.14;".
I don't understand your understanding, sorry. If you intend to refer to
the same object from anywhere in your code, you need to make sure that
you declare it *the same way* everywhere.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 14 '08 #11
Ioannis Vranos wrote:
[..]
Victor check TC++PL3 on page 200.
And what am I going to find there? Could you simply type the gist of it
here?
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 14 '08 #12
On Oct 14, 7:08*pm, Ioannis Vranos <ivra...@no.spam.nospamfreemail.gr>
wrote:
shuisheng wrote:
I am always confused in using constants in multiple files.
For global constants, I got some clues from
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx
So in header file writing: * const double PI = 3.14;
Every time using it, include the header file.
But how about constants in namespaces and classes?
1. The easiest constants in classes are made by using enums:
#include <vector>
class SomeClass
{
* * *enum { SIZE= 7 };
* * *int array[SIZE];
* * *std::vector<intintVector;
* * *public:
* * * * *SomeClass(): intVector(SIZE) {}
};
Two problems with this. The first is that it can only be used
for integral constants; it doesn't work for floating point (the
actual example) or user defined types. The second is that even
for integral constants, the type is wrong, which has
repercusions with regards to function overload resolution and
templates.

The usual solution here is to declare a static const member,
e.g.:

class SomeClass
{
public:
static std::size_t const size = 7 ;
static double const pi ;
// ...
} ;

In all cases, you must define the variable in a single source
file. In the case of an integral constant, you can put the
initializer (the value) either in the declaration in the class,
or in the definition. For all other types, the initializer can
only go in the definition.
2. Regarding global constants and the header file you mentioned, in
simple words:
You can #include the header file with the global constant only in one
"implementation" file (e.g. .cpp) and to the rest implementation files
(e.g. .cpp), you can add the declaration:
extern const double PI;
In that case, you must also declare the definition extern:

extern double const PI = 3.14 ;

Otherwise, it doesn't have external linkage.

It's more frequent to simply write:

double const PI = 3.14 ;

in the header. Be aware, however, that this means that &PI may
not always be the same thing. (Not usually a problem for the
standard arithmetic types, but it easily could be a problem with
user defined types.)
==In general avoid objects in the global namespace.
Except maybe for some global constants:-).
3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. *by placing it in the header file).
file1.cpp:
E.g. pi.h:

namespace SomeNamespace
{
* * *const double PI = 3.14;
}
What should be preferred instead of constants in the global
namespace:
Constants (consts/enums) in anonymous namespaces (= local file
scope only), and constants (consts/enums) in named namespaces.
I don't think that that's a good general policy. You don't want
to have an anonymous namespace in a header, since it's generally
a very good way to end up with undefined behavior.
Regarding classes, you can either use static constants or
(usually better) enums.
Enums were what was used before the rules were changed to allow
the initializer in the declaration. The rule was changed
because using enums created too many problems due to the type
being wrong.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 14 '08 #13
James Kanze wrote:
>
>1. The easiest constants in classes are made by using enums:
>#include <vector>
>class SomeClass
{
enum { SIZE= 7 };
> int array[SIZE];
> std::vector<intintVector;
> public:
SomeClass(): intVector(SIZE) {}
};

Two problems with this. The first is that it can only be used
for integral constants; it doesn't work for floating point (the
actual example) or user defined types.

Yes, my notion was "where applicable".

The second is that even
for integral constants, the type is wrong, which has
repercusions with regards to function overload resolution and
templates.

What you mean "the type is wrong"? If I defined it as a
static const short SIZE;

inside the function declaration, would the type be right?

I don't think that that's a good general policy. You don't want
to have an anonymous namespace in a header, since it's generally
a very good way to end up with undefined behavior.

Speaking about local file scope (or better compilation unit - scope), I
implied the anonymous namespaces are to be used in .cpp files.
Oct 14 '08 #14
James Kanze wrote:
>
>1. The easiest constants in classes are made by using enums:
>#include <vector>
>class SomeClass
{
enum { SIZE= 7 };
> int array[SIZE];
> std::vector<intintVector;
> public:
SomeClass(): intVector(SIZE) {}
};

Two problems with this. The first is that it can only be used
for integral constants; it doesn't work for floating point (the
actual example) or user defined types.

Yes, my notion was "where applicable".

The second is that even
for integral constants, the type is wrong, which has
repercusions with regards to function overload resolution and
templates.

What you mean "the type is wrong"? If I defined it as a
static const short SIZE;

inside the class declaration, would the type be right?

I don't think that that's a good general policy. You don't want
to have an anonymous namespace in a header, since it's generally
a very good way to end up with undefined behavior.

Speaking about local file scope (or better compilation unit - scope), I
implied the anonymous namespaces are to be used in .cpp files.


Oct 14 '08 #15
Ioannis Vranos wrote:
[..]
Speaking about local file scope (or better compilation unit - scope), I
implied the anonymous namespaces are to be used in .cpp files.
What would be the difference for a constant (or its use) if it's defined
inside the anonymous namespace versus if it's defined in the global
namespace? Unless somebody else introduces the declaration of the same
constant with external linkage in some header included in this TU
previously to the definition of the constant, what is there to worry
about? Why the anonymous namespace?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 14 '08 #16
Victor Bazarov wrote:
Ioannis Vranos wrote:
>[..]
Speaking about local file scope (or better compilation unit - scope),
I implied the anonymous namespaces are to be used in .cpp files.

What would be the difference for a constant (or its use) if it's defined
inside the anonymous namespace versus if it's defined in the global
namespace? Unless somebody else introduces the declaration of the same
constant with external linkage in some header included in this TU
previously to the definition of the constant, what is there to worry
about? Why the anonymous namespace?

In a facilities (library) notion, we must always try not polluting the
global namespace.
An example: Using the "using namespace std;" statement in global scope,
is an attempt to defeat the namespace system.

Namespaces exist to isolate our code in modules.
In general, it is good to create our program as a library.
Oct 15 '08 #17
Ioannis Vranos wrote:
>
In a facilities (library) notion, we must always try not polluting the
global namespace.
An example: Using the "using namespace std;" statement in global scope,
is an attempt to defeat the namespace system.

Namespaces exist to isolate our code in modules.
In general, it is good to create our program as a library.

In the case of global non-extern consts, the effect is the same as if
they are defined in an anonymous namespace, but it is easier to place
everything in a suitable namespace, rather than thinking such subtle
details.
Oct 15 '08 #18
Ioannis Vranos wrote:
>
In a facilities (library) notion, we must always try not polluting
the global namespace.
>

An example: Using the "using namespace std;" statement in global
scope, is an attempt to defeat the namespace system.
>
Namespaces exist to isolate our code in modules.
In general, it is good to create our program as a library.

In the case of global non-extern consts, the effect is the same as if
they are defined in an anonymous namespace, but it is easier to place
everything in a suitable namespace, rather than thinking such subtle
details.
Oct 15 '08 #19
Ioannis Vranos wrote:
Victor Bazarov wrote:
>Ioannis Vranos wrote:
>>[..]
Speaking about local file scope (or better compilation unit - scope),
I implied the anonymous namespaces are to be used in .cpp files.

What would be the difference for a constant (or its use) if it's
defined inside the anonymous namespace versus if it's defined in the
global namespace? Unless somebody else introduces the declaration of
the same constant with external linkage in some header included in
this TU previously to the definition of the constant, what is there to
worry about? Why the anonymous namespace?


In a facilities (library) notion, we must always try not polluting the
global namespace.
An example: Using the "using namespace std;" statement in global scope,
is an attempt to defeat the namespace system.

Namespaces exist to isolate our code in modules.
In general, it is good to create our program as a library.
Please answer the concrete question. What would be the reason to have
constants in the *anonymous* namespace as compared to the *global*
namespace? Concrete answer, please. If you don't have one, say so.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 15 '08 #20
Ioannis Vranos wrote:
Ioannis Vranos wrote:
>
In a facilities (library) notion, we must always try not polluting
the global namespace.
>
>
An example: Using the "using namespace std;" statement in global
scope, is an attempt to defeat the namespace system.
>
Namespaces exist to isolate our code in modules.
>
>
In general, it is good to create our program as a library.


In the case of global non-extern consts, the effect is the same as if
they are defined in an anonymous namespace, but it is easier to place
everything in a suitable namespace, rather than thinking such subtle
details.
"Suitable namespace"? "Thinking such subtle details"? If "the effect
is the same", then there is no difference, is there? Please try to
imagine somebody reading your posts and attempting to extract some kind
of technical objective truth out of them. Imagine that the reader needs
to come up with a brief description of the reasons to use anonymous
namespaces for constants, and report to their manager. What would the
technical reason[s] be? "Easier to place" - compared to what? Is the
easiness in the additional symbols before and after the constant
definitions?
--------------------------------------- global namespace
const double PI = 3.14159;
const double g = 9.81;
const double inch = 25.4;
------------------------------------ anonymous namespace
namespace {
const double PI = 3.14159;
const double g = 9.81;
const double inch = 25.4;
}
---------------------------------------------------------

How is the latter "easier" than the former?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 15 '08 #21
On Oct 15, 4:07 am, Victor Bazarov <v.Abaza...@comAcast.netwrote:
Ioannis Vranos wrote:
Ioannis Vranos wrote:
In a facilities (library) notion, we must always try not
polluting the global namespace.
An example: Using the "using namespace std;" statement in
global scope, is an attempt to defeat the namespace
system.
Namespaces exist to isolate our code in modules.
In general, it is good to create our program as a library.
In the case of global non-extern consts, the effect is the
same as if they are defined in an anonymous namespace, but
it is easier to place everything in a suitable namespace,
rather than thinking such subtle details.
"Suitable namespace"? "Thinking such subtle details"? If
"the effect is the same", then there is no difference, is
there? Please try to imagine somebody reading your posts and
attempting to extract some kind of technical objective truth
out of them.
There is a very strong technical argument for *not* putting them
in anonymous namespace. You don't want anonymous namespaces in
a header file, and I would imagine that most coding guidelines
forbid them. Since there is nothing to be gained by putting
constants in an anonymous namespace, there is no reason to make
an exception to this rule for constants.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 15 '08 #22
On Tue, 14 Oct 2008 15:27:24 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>Enums were what was used before the rules were changed to allow
the initializer in the declaration. The rule was changed
because using enums created too many problems due to the type
being wrong.
Never had that problem myself - I'm careful how I overload my integers
for reasons that are nothing to do with enum, and everything to do
with my failed portable code ideals. You never know whether int will
be considered the same type as long int and so on - even though
they're normally the same type in the set-of-values sense, and have
been since the days of 16-bit ints.

Enums are still being used - old habits die hard - it's just that it's
naughtier than it used to be.

Oct 15 '08 #23
Stephen Horne wrote:
On Tue, 14 Oct 2008 15:27:24 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>Enums were what was used before the rules were changed to allow
the initializer in the declaration. The rule was changed
because using enums created too many problems due to the type
being wrong.

Never had that problem myself - I'm careful how I overload my integers
for reasons that are nothing to do with enum, and everything to do
with my failed portable code ideals. You never know whether int will
be considered the same type as long int and so on - even though
they're normally the same type in the set-of-values sense, and have
been since the days of 16-bit ints.
Not really, long is at least 32 bit and most 64 bit systems that aren't
windows use 32 bit int and 64 bit long.

--
Ian Collins
Oct 15 '08 #24
On Wed, 15 Oct 2008 01:46:16 +0300, Ioannis Vranos
<iv*****@no.spam.nospamfreemail.grwrote:
The second is that even
for integral constants, the type is wrong, which has
repercusions with regards to function overload resolution and
templates.


What you mean "the type is wrong"? If I defined it as a
static const short SIZE;

inside the class declaration, would the type be right?
Different, certainly.

From Stroustrup : "Each enumeration is a distinct type."

This applies to anonymous enums too, AFAIK.

Therefore, an enum doesn't match any particular integer type (other
than itself) for overloading, so casting rules apply. And then you get
into which-types-are-considered-the-same issues and so on.

For what it's worth, IMO your example was fine.

Oct 15 '08 #25
On Wed, 15 Oct 2008 20:39:44 +1300, Ian Collins <ia******@hotmail.com>
wrote:
>Stephen Horne wrote:
>On Tue, 14 Oct 2008 15:27:24 -0700 (PDT), James Kanze
<ja*********@gmail.comwrote:
>>Enums were what was used before the rules were changed to allow
the initializer in the declaration. The rule was changed
because using enums created too many problems due to the type
being wrong.

Never had that problem myself - I'm careful how I overload my integers
for reasons that are nothing to do with enum, and everything to do
with my failed portable code ideals. You never know whether int will
be considered the same type as long int and so on - even though
they're normally the same type in the set-of-values sense, and have
been since the days of 16-bit ints.
Not really, long is at least 32 bit and most 64 bit systems that aren't
windows use 32 bit int and 64 bit long.
Most platforms *are* Windows ;-)

OK, I could easily be wrong on that one.

Obviously, I rarely spell out the standard integer types directly,
except for plain int and size_t (and even size_t has caused problems).
All this vague short/long/etc nonsense first bit me a very long time
ago. Now, I don't really care how the compiler spells 64-bits, other
than when I'm adding a new #ifdef block to the relevant file.

What's the odds on "really totally enormously gigantic int" being
added in the 2050 C and C++ standards?

And how come we got the strangely sensible "bool" instead of "itty
bitty tiny int"?

Oct 15 '08 #26
Victor Bazarov wrote:
>
Please answer the concrete question. What would be the reason to have
constants in the *anonymous* namespace as compared to the *global*
namespace? Concrete answer, please. If you don't have one, say so.

Good coding guidelines I guess. Imagine the situation

file1.cpp:
const double PI= 3.14;

namespace
{
double dpi= 2* PI;
}
Oct 15 '08 #27
Victor Bazarov wrote:
shuisheng wrote:
>[..]
So I think the following is the right way, please confirm it. I
use PI as an example.

For global constants:

// in constants.h
const double PI = 3.14;

// in h or cpp files to use PI
#include "constants.h"
double a = PI;
For constants in namespace:

// in constants.h
namespace constants
{
const double PI = 3.14;
};

// in h or cpp files to use PI
#include "constants.h"
double d = constants::PI;
For constants in classes:

// in class.h
class A
{
public:
static const double PI;
};

// in class.cpp
const double A::PI = 3.14;

// in h and cpp files to use it.
#include "class.h"
double a = A::PI;

And I think Ioannis Vranos's way to define global constants will
bring about problems as shown in
http://msdn.microsoft.com/en-us/libr...2d(VS.80).aspx

The code you showed here is perfectly fine, and you can
declare/define any constants that way, not just of fundamental
types, AFAIC.
The contents of the web page you cited do bother me. I am not sure
what "static linkage" is; there is no such term in C++ Standard. Why
would the page say that "If you try to use a global constant in
C++ in multiple files you get an unresolved external error"? What
kind of nonsense is that?
The page just IS nonsense, as it has a "const int" in one file and an
"extern int" in another file. Of course the linker will not connect
these two. It shouldn't!
Bo Persson
Oct 15 '08 #28
Ioannis Vranos wrote:
Victor Bazarov wrote:
>>
Please answer the concrete question. What would be the reason to
have constants in the *anonymous* namespace as compared to the
*global* namespace? Concrete answer, please. If you don't have
one, say so.


Good coding guidelines I guess. Imagine the situation

file1.cpp:
const double PI= 3.14;

namespace
{
double dpi= 2* PI;
}
Well, since you wrote it down, I don't have to imagine it. Did
you have a point to make with this example?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 15 '08 #29
James Kanze wrote:
[..]
There is a very strong technical argument for *not* putting them
in anonymous namespace.
There is? Care to provide it?
You don't want anonymous namespaces in
a header file, and I would imagine that most coding guidelines
forbid them.
Why? Please don't mind me. Explain as if a newbie was asking.
Since there is nothing to be gained by putting
constants in an anonymous namespace, there is no reason to make
an exception to this rule for constants.
To which rule?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 15 '08 #30
On Wed, 15 Oct 2008 19:23:54 -0400, "Victor Bazarov"
<v.********@comAcast.netwrote:
>James Kanze wrote:
>[..]
There is a very strong technical argument for *not* putting them
in anonymous namespace.

There is? Care to provide it?
Since each body file and therefore each object file gets its own copy
of the constant, you have multiple copies. Despite the constness, one
or more could be modified (const_cast, memory corruption etc).

Of course if you're modifying your constants, you're probably digging
a hole for yourself anyway. In fact you could argue that having
multiple copies might limit the scope of errors resulting from memory
corruption - though it could just as easily confuse you when you're
trying to debug that memory corruption.

Personally, I don't see a "very strong" argument. I wouldn't do it
myself, but that's as far as I'd go.

Oct 16 '08 #31
On Tue, 14 Oct 2008 22:01:04 -0400, Victor Bazarov
<v.********@comAcast.netwrote:
>Please answer the concrete question. What would be the reason to have
constants in the *anonymous* namespace as compared to the *global*
namespace? Concrete answer, please. If you don't have one, say so.
I'm missing something here. I thought "don't pollute the global
namespace" was a concrete answer.

Oct 16 '08 #32
Stephen Horne wrote:
On Tue, 14 Oct 2008 22:01:04 -0400, Victor Bazarov
<v.********@comAcast.netwrote:
>Please answer the concrete question. What would be the reason to have
constants in the *anonymous* namespace as compared to the *global*
namespace? Concrete answer, please. If you don't have one, say so.

I'm missing something here. I thought "don't pollute the global
namespace" was a concrete answer.
Really?

What functionality of the anonymous namespace do you not understand?
Even in the Standard the explanation is given in simple enough terms:
declaring an anonymous namespace in a translation unit is basically
akin to doing

namespace SomeSpecificYetUnknownFromOutsideName {
your declarations;
}

using namespace SomeSpecificYetUnknownFromOutsideName;

What is this if not "polluting" the global namespace? All the names
declared in the anonymous namespaces *are* in the global namespace
right after the essential "using" directive. That's what the whole
point of the anonymous namespace is. The only difference from the
global namespace is that the names, while having the external linkage
(for those that do), aren't found from outside the module since they
are *unknown*. Still, any *constant* declared in the anonymous
namespace does *not* have external linkage because it's a *constant*.

Wake up, Stephen!

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 16 '08 #33
On Oct 16, 1:23 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
James Kanze wrote:
[..]
There is a very strong technical argument for *not* putting
them in anonymous namespace.
There is? Care to provide it?
Yes. It leads too easily to violations of the one definition
rule. It doesn't do what is usually wanted.
You don't want anonymous namespaces in a header file, and I
would imagine that most coding guidelines forbid them.
Why? Please don't mind me. Explain as if a newbie was
asking.
Because it leads to accidental violations of the one definition
rule. Remember that for the multiple definitions (e.g. of
classes, templates or inline functions) to not be inviolation of
the one definition rule, not only must the token sequence in the
definition be identical; all symbols must also bind identically
as well. The only exception is if the symbol binds to a const
object, with a visible initializer, and only the value is used
(e.g. it's either used in a context which requires a const
expression, or there is an immediate lvalue to rvalue
conversion). Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.
Since there is nothing to be gained by putting constants in
an anonymous namespace, there is no reason to make an
exception to this rule for constants.
To which rule?
The the rule not to use anonymous namespace in a header.

Like all rules, it admits exceptions. But as it is a good
general rule, it's better to follow it unless there are
distinct reasons for not doing so. In this case, there's no
real advantage in breaking it, so it's probably better to
respect it.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 16 '08 #34
On Oct 16, 12:12*pm, James Kanze <james.ka...@gmail.comwrote:
On Oct 16, 1:23 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
James Kanze wrote:
[..]
There is a very strong technical argument for *not* putting
them in anonymous namespace.
There is? *Care to provide it?

Yes. *It leads too easily to violations of the one definition
rule. *It doesn't do what is usually wanted.
You don't want anonymous namespaces in a header file, and I
would imagine that most coding guidelines forbid them.
Why? *Please don't mind me. *Explain as if a newbie was
asking.

Because it leads to accidental violations of the one definition
rule. *Remember that for the multiple definitions (e.g. of
classes, templates or inline functions) to not be inviolation of
the one definition rule, not only must the token sequence in the
definition be identical; all symbols must also bind identically
as well. *The only exception is if the symbol binds to a const
object, with a visible initializer, and only the value is used
(e.g. it's either used in a context which requires a const
expression, or there is an immediate lvalue to rvalue
conversion). *Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.
Is this exception explicitly given in the standard or must be inferred
somehow? Do you have a pointer?

Thanks,

--
Giovanni P. Deretta
Oct 16 '08 #35
On Oct 15, 9:38 am, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
On Tue, 14 Oct 2008 15:27:24 -0700 (PDT), James Kanze
<james.ka...@gmail.comwrote:
Enums were what was used before the rules were changed to
allow the initializer in the declaration. The rule was
changed because using enums created too many problems due to
the type being wrong.
Never had that problem myself
I haven't either. But I've very conservative in my use of
overloading and templates; there are cases where it makes a
difference.
- I'm careful how I overload my integers for reasons that are
nothing to do with enum, and everything to do with my failed
portable code ideals. You never know whether int will be
considered the same type as long int and so on - even though
they're normally the same type in the set-of-values sense, and
have been since the days of 16-bit ints.
int and long int are never the same type. At least not with a
conforming compiler, and I've never encountered compiler which
didn't conform in this regard. (It was, after all, already the
rule in K&R C.)

As for both supporting the same set-of-values, I don't know. In
terms of different types of systems, probably not---most Unix
systems have 64 bit longs, but 32 bit ints. In terms of numbers
of machines, I'm not up to date as to what is being used in the
embedded world (which probably accounts for something like 90%
of all machines)---when I worked in it, 8 bit processors were
the rule, and 16 bit machines were considered really big.
(There's also the question as to how relevant this is to C++.
One common processor when I worked in embedded software only had
64 bytes of RAM. Somehow, I'm sure that even if it's still
around, it doesn't have a C++ compiler. Using std::vector in 64
bytes would be somewhat of a challenge.)
Enums are still being used - old habits die hard - it's just
that it's naughtier than it used to be.
I forget when I made the move over, but it wasn't all that long
ago. And the reason I delayed was that I had to support a
compiler which didn't support initializers in the class
definition for static const ints. Still, given the way most
people seem to overload and use templates, it's probably best
avoided.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 16 '08 #36
James Kanze wrote:
On Oct 16, 1:23 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>James Kanze wrote:
>>[..]
There is a very strong technical argument for *not* putting
them in anonymous namespace.
>There is? Care to provide it?

Yes. It leads too easily to violations of the one definition
rule. It doesn't do what is usually wanted.
Please, feel free to provide some examples. I for one don't see placing
anonymous namespaces in headers "leading easily" to violations of ODR.
Do continue, I'm biting.
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 16 '08 #37
gpderetta wrote:
On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
>Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.

Is this exception explicitly given in the standard or must be inferred
somehow? Do you have a pointer?
An unnamed namespace goes --as per language definition-- like
this

namespace unique { }
using namespace unique ;
namespace unique { /* your stuff */ }

where "unique" is a name generated by the compiler, unique per
*translation unit* (not file). So, if you include e.g.

// a.hpp
namespace {
class A {} ;
}

from e.g. f1.cpp and f2.cpp you end up with two A classes, one
in namespace --let's call it-- f1_unique, and another one in
f2_unique. Now, consider two source files which include the
following:

// useful.hpp
#include "a.hpp"

class useful
{
A a_ ;
...
} ;

Those two source files will contain two different definitions of
class useful.

--
Gennaro Prota | name.surname yahoo.com
Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
Do you need expertise in C++? I'm available.
Oct 16 '08 #38
Gennaro Prota wrote:
gpderetta wrote:
>On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
>>Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.

Is this exception explicitly given in the standard or must be inferred
somehow? Do you have a pointer?

An unnamed namespace goes --as per language definition-- like
this

namespace unique { }
using namespace unique ;
namespace unique { /* your stuff */ }

where "unique" is a name generated by the compiler, unique per
*translation unit* (not file). So, if you include e.g.

// a.hpp
namespace {
class A {} ;
}

from e.g. f1.cpp and f2.cpp you end up with two A classes, one
in namespace --let's call it-- f1_unique, and another one in
f2_unique. Now, consider two source files which include the
following:

// useful.hpp
#include "a.hpp"

class useful
{
A a_ ;
...
} ;

Those two source files will contain two different definitions of
class useful.
This is a great example that could lead to quite an obscure coding
guideline. Of course, a good compiler would issue a warning if a type
from an unnamed namespace would be used to define another type which
isn't in the [same] unnamed namespace. We could lobby the compiler
vendors to include such analysis, it wouldn't be difficult for them to
introduce, I suppose.

Not sure if tools like PC-lint already have a way to recognize this kind
of a problem. Anybody has any idea?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 16 '08 #39
On Oct 16, 5:12*pm, Gennaro Prota <gennaro/pr...@yahoo.comwrote:
gpderetta wrote:
On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.comwrote:
* * *[...]
Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.
Is this exception explicitly given in the standard or must be inferred
somehow? Do you have a pointer?

An unnamed namespace goes --as per language definition-- like
this

* *namespace unique { }
* *using namespace unique ;
* *namespace unique { /* your stuff */ }

where "unique" is a name generated by the compiler, unique per
*translation unit* (not file). So, if you include e.g.

* *// a.hpp
* *namespace {
* * *class A {} ;
* *}

from e.g. f1.cpp and f2.cpp you end up with two A classes, one
in namespace --let's call it-- f1_unique, and another one in
f2_unique. Now, consider two source files which include the
following:

* *// useful.hpp
* *#include "a.hpp"

* *class useful
* *{
* * *A a_ ;
* * *...
* *} ;

Those two source files will contain two different definitions of
class useful.
I'm aware of that, I was referring to the exception stated by James
Kanze:

" The only exception is if the symbol binds to a const
object, with a visible initializer, and only the value is used
(e.g. it's either used in a context which requires a const
expression, or there is an immediate lvalue to rvalue
conversion "

--
gpd
Oct 16 '08 #40
On Oct 16, 5:46*pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
Gennaro Prota wrote:
gpderetta wrote:
On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.comwrote:
* * [...]
>Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.
Is this exception explicitly given in the standard or must be inferred
somehow? Do you have a pointer?
An unnamed namespace goes --as per language definition-- like
this
* namespace unique { }
* using namespace unique ;
* namespace unique { /* your stuff */ }
where "unique" is a name generated by the compiler, unique per
*translation unit* (not file). So, if you include e.g.
* // a.hpp
* namespace {
* * class A {} ;
* }
from e.g. f1.cpp and f2.cpp you end up with two A classes, one
in namespace --let's call it-- f1_unique, and another one in
f2_unique. Now, consider two source files which include the
following:
* // useful.hpp
* #include "a.hpp"
* class useful
* {
* * A a_ ;
* * ...
* } ;
Those two source files will contain two different definitions of
class useful.

This is a great example that could lead to quite an obscure coding
guideline. *Of course, a good compiler would issue a warning if a type
from an unnamed namespace would be used to define another type which
isn't in the [same] unnamed namespace. *We could lobby the compiler
vendors to include such analysis, it wouldn't be difficult for them to
introduce, I suppose.
It is not just a matter of types, consider this:

// in foo.hpp
struct my_functor_type {...};

namespace { my_functor_type bar; }

template<class Tvoid foo(T x) {
bar(x);
}

Now, if foo is instantiated in two translation units with the same T,
it will lead to ODR violation.
This is not a made up example, I often find the need to name function
object instances in header files, but, if the anonymous namespace is
dropped, you will get multiple definitions for 'bar'.
The only workaround I know (from the boost mailing list) is:

template <class Fstruct instance_of { static T value; };
template<class TT instance_of<T>::value = {}

namespace { my_functor_type const& bar =
instance_of<my_functor_type>::value; }
template<class Tvoid foo(T x) {
bar(x);
}

Now there won't be any ODR violations in 'foo', if the ODR rule is
interpret as only requiring all symbols to bind to the same objects in
all translation units.

The idea is that, as per the standard, a reference is not an object
but is really an alias for an object (which will be the same for all
translation units: the compiler will take care of that).

--
gpd

Oct 16 '08 #41
gpderetta wrote:
On Oct 16, 5:12 pm, Gennaro Prota <gennaro/pr...@yahoo.comwrote:
[...]
>Those two source files will contain two different definitions of
class useful.

I'm aware of that, I was referring to the exception stated by James
Kanze:

" The only exception is if the symbol binds to a const
object, with a visible initializer, and only the value is used
(e.g. it's either used in a context which requires a const
expression, or there is an immediate lvalue to rvalue
conversion "
Ah, sorry, I misread your post. Well it's in the standard ODR
prayer, in clause 3 (note that it is restricted to objects with
internal linkage or no linkage).

--
Gennaro Prota | name.surname yahoo.com
Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
Do you need expertise in C++? I'm available.
Oct 16 '08 #42
gpderetta wrote:
It is not just a matter of types, consider this:

// in foo.hpp
struct my_functor_type {...};

namespace { my_functor_type bar; }

template<class Tvoid foo(T x) {
bar(x);
}

Now, if foo is instantiated in two translation units with the same T,
it will lead to ODR violation.
Do you mean that there's no violation if you instantiate on
different T's?
This is not a made up example, I often find the need to name function
object instances in header files,
Out of curiosity, why?

--
Gennaro Prota | name.surname yahoo.com
Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
Do you need expertise in C++? I'm available.
Oct 16 '08 #43
Victor Bazarov wrote:
[...]
>Those two source files will contain two different definitions of
class useful.

This is a great example that could lead to quite an obscure coding
guideline.
Why obscure?
Of course, a good compiler would issue a warning if a type
from an unnamed namespace would be used to define another type which
isn't in the [same] unnamed namespace. We could lobby the compiler
vendors to include such analysis, it wouldn't be difficult for them to
introduce, I suppose.
I'd love if we had such a power. But do we? (FWIW, I've never
liked the Boost praxis of supporting all broken compilers of the
world; at least, if the library becomes attractive to many
users, and it doesn't work with their compiler, they may put
pressure, complain or switch to another one; if it is supported,
instead, how can you expect the vendor to improve it?)

--
Gennaro Prota | name.surname yahoo.com
Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
Do you need expertise in C++? I'm available.
Oct 16 '08 #44
On Thu, 16 Oct 2008 00:15:25 -0400, Victor Bazarov
<v.********@comAcast.netwrote:
>I'm missing something here. I thought "don't pollute the global
namespace" was a concrete answer.
namespace SomeSpecificYetUnknownFromOutsideName {
your declarations;
}

using namespace SomeSpecificYetUnknownFromOutsideName;

What is this if not "polluting" the global namespace?
Depends what you mean by *global* namespace. They pollute the source
code that includes them, but they don't pollute the linkers namespace,
which is more likely the point. Global *within* a set of compilation
units isn't the same as simply global.
>Wake up, Stephen!
I'm awake - I just recognise that if someone #includes a header, they
are obviously *requesting* a certain amount of namespace "pollution",
local to that particular compilation unit. In a large project,
however, it can be important to limit the effect of that pollution to
the source files that specifically request it.

You can't program without polluting namespaces to a degree - even a
namespace pollutes its parent namespace. Different degrees of
pollution are appropriate to the global namespace depending on what
you mean by "global".

Oct 17 '08 #45
On Thu, 16 Oct 2008 17:12:10 +0200, Gennaro Prota
<gennaro/pr***@yahoo.comwrote:
>Those two source files will contain two different definitions of
class useful.
Which are both in different namespaces. Impossible to provide
implementation stuff unless it/they are already fully implemented, but
even so. It does what it's supposed to do, in accordance with the
standard.

More to the point, every construct has unsafe uses, and every style
guideline is inherently an overgeneralisation WRT avoiding those
unsafe uses. Different people have differing style rules, implying
differing generalisations of what is unsafe.

The original example was using constants. Criticising that is valid,
if you have a legitimate criticism. Criticising it because putting
*other* stuff in an anonymous namespace in a header is unsafe, IMO, is
not.

Pushing the principle to an extreme, you may as well say that all
values should be banned because a reinterpret_cast of any value is
unsafe.

Oct 17 '08 #46
Stephen Horne wrote:
On Thu, 16 Oct 2008 17:12:10 +0200, Gennaro Prota
<gennaro/pr***@yahoo.comwrote:
>Those two source files will contain two different definitions of
class useful.

Which are both in different namespaces.
No, they are not. Please don't snip away the code you are referring to,
doing so makes your postings meaningless.

The example was

#include "a.hpp"

class useful
{
A a_ ;
...
} ;

where A was declared in a.hpp in an unnamed namespace.
Impossible to provide
implementation stuff unless it/they are already fully implemented, but
even so. It does what it's supposed to do, in accordance with the
standard.
What?
More to the point, every construct has unsafe uses, and every style
guideline is inherently an overgeneralisation WRT avoiding those
unsafe uses. Different people have differing style rules, implying
differing generalisations of what is unsafe.
The quoted example is well passed unsafe.
The original example was using constants. Criticising that is valid,
if you have a legitimate criticism. Criticising it because putting
*other* stuff in an anonymous namespace in a header is unsafe, IMO, is
not.
How can we tell when you removed it?
Pushing the principle to an extreme, you may as well say that all
values should be banned because a reinterpret_cast of any value is
unsafe.
Twaddle.

--
Ian Collins
Oct 17 '08 #47
On Fri, 17 Oct 2008 20:11:19 +1300, Ian Collins <ia******@hotmail.com>
wrote:
#include "a.hpp"

class useful
{
A a_ ;
...
} ;
Whoops - yes, you're right. Sorry - brain failure - I though "useful"
was in the anonymous namespace.
>The original example was using constants. Criticising that is valid,
if you have a legitimate criticism. Criticising it because putting
*other* stuff in an anonymous namespace in a header is unsafe, IMO, is
not.
How can we tell when you removed it?
No-one is going to spend that much time second-guessing whether
they've left sufficient context in a post. My bad, but you only need
to make the point once.

After getting the point that was actually being made, it obviously
extends to constants, but *maybe* it could be argued that it depends
on the constant. In the context (which someone else snipped, not me)
we're talking about these...

: const double PI = 3.14159;
: const double g = 9.81;
: const double inch = 25.4;

A class may have constants with values derived from these. I doubt
that it would become double-defined because of that, since the values
remain the same, but I could be wrong.

There are possibilities that *would* cause double definition, but they
seem pretty unlikely.

Of course once you start a list of constants, it's an invitation for
more to be added, and once you get an array size or some such...

So yes, I'm wrong on this one, thinking it through properly. I still
think there's a get-out clause for that particular usage, but I
wouldn't have said what I said if I understood the point being made.

Sorry for being such an idiot.

Oct 17 '08 #48
On Oct 16, 5:46 pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
Gennaro Prota wrote:
gpderetta wrote:
On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
>Refer to almost anything in an anonymous namespace in a
header, and you end up with undefined behavior.
Is this exception explicitly given in the standard or must
be inferred somehow? Do you have a pointer?
An unnamed namespace goes --as per language definition--
like this
namespace unique { }
using namespace unique ;
namespace unique { /* your stuff */ }
where "unique" is a name generated by the compiler, unique
per *translation unit* (not file). So, if you include e.g.
// a.hpp
namespace {
class A {} ;
}
from e.g. f1.cpp and f2.cpp you end up with two A classes,
one in namespace --let's call it-- f1_unique, and another
one in f2_unique. Now, consider two source files which
include the following:
// useful.hpp
#include "a.hpp"
class useful
{
A a_ ;
...
} ;
Those two source files will contain two different
definitions of class useful.
This is a great example that could lead to quite an obscure
coding guideline. Of course, a good compiler would issue a
warning if a type from an unnamed namespace would be used to
define another type which isn't in the [same] unnamed
namespace. We could lobby the compiler vendors to include
such analysis, it wouldn't be difficult for them to introduce,
I suppose.
Except that it's actually very frequent for a class to use
something defined in an anonymous namespace. There's nothing
wrong with that, and banning it, or even warning about it, would
make the compilation firewall idiom a pain.

What the compiler could warn about is if a definition (any
definition) in a header file (but not e.g. the definition of
Toto::Impl, which is in Toto.cc) used a definition from an
anonymous namespace in an illegal way. Although I suspect that
it might be difficult to implement the warning when the use is
in a template, especially if it is in a dependent context. (Of
course, it's so easy to get violations of the one definition
rule in dependent contexts that one more probably doesn't matter
much.)

The real issue is, given the risk, are there any legal cases
where one might legitimately want to use an anonymous namespace
in a header. I can't think of one, really: if I'm using the
symbol in a header, about the only time the use would be legal
is if the symbol is a constant, and in that case, the anonymous
namespace really buys you nothing, since const variables have
internal linkage by default.
Not sure if tools like PC-lint already have a way to recognize
this kind of a problem. Anybody has any idea?
Have a rule forbidding anonymous namespaces in a header file:-).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 17 '08 #49
On Oct 16, 6:58 pm, gpderetta <gpdere...@gmail.comwrote:
On Oct 16, 5:46 pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
Gennaro Prota wrote:
gpderetta wrote:
>On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
>>Refer to almost anything in an anonymous namespace
>>in a header, and you end up with undefined behavior.
>Is this exception explicitly given in the standard or
>must be inferred somehow? Do you have a pointer?
An unnamed namespace goes --as per language definition--
like this
namespace unique { }
using namespace unique ;
namespace unique { /* your stuff */ }
where "unique" is a name generated by the compiler, unique
per *translation unit* (not file). So, if you include e.g.
// a.hpp
namespace {
class A {} ;
}
from e.g. f1.cpp and f2.cpp you end up with two A classes, one
in namespace --let's call it-- f1_unique, and another one in
f2_unique. Now, consider two source files which include the
following:
// useful.hpp
#include "a.hpp"
class useful
{
A a_ ;
...
} ;
Those two source files will contain two different
definitions of class useful.
This is a great example that could lead to quite an obscure coding
guideline. Of course, a good compiler would issue a warning if a type
from an unnamed namespace would be used to define another type which
isn't in the [same] unnamed namespace. We could lobby the compiler
vendors to include such analysis, it wouldn't be difficult for them to
introduce, I suppose.
It is not just a matter of types, consider this:
// in foo.hpp
struct my_functor_type {...};
namespace { my_functor_type bar; }
template<class Tvoid foo(T x) {
bar(x);
}
Now, if foo is instantiated in two translation units with the
same T, it will lead to ODR violation.
Yes. This is what I consider the real problem. Templates
require their definition to be in the header file, and the
one definition rule to apply to all potential instantiations
(even if in practice, most compilers will just pick one, and
throw out any others).
This is not a made up example, I often find the need to name
function object instances in header files, but, if the
anonymous namespace is dropped, you will get multiple
definitions for 'bar'. The only workaround I know (from the
boost mailing list) is:
template <class Fstruct instance_of { static T value; };
template<class TT instance_of<T>::value = {}
namespace { my_functor_type const& bar =
instance_of<my_functor_type>::value; }
template<class Tvoid foo(T x) {
bar(x);
}
Typical Boost:-). Why do simple when you can do complicated:

namespace Whatever_Private
{
extern my_functor_type bar ;
} ;

Or if you really need to be headers only:

namespace Whatever_Private
{
inline my_functor_type& bar()
{
static my_functor_type theOneAndOnly ;
return theOneAndOnly ;
}
} ;

In sum, the classical solutions (but it just ain't Boost if it
ain't got the templates).

(Seriously, there's a lot I like about Boost. But they do get
carried away sometimes.)
Now there won't be any ODR violations in 'foo', if the ODR
rule is interpret as only requiring all symbols to bind to the
same objects in all translation units.
If you want the library to be headers only, then you need to
encapsulate the definition in something which can appear in
multiple compilation units: a template or an inline function.
Generally, you're better off dropping the headers only
requirement, however.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 17 '08 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Sugapablo | last post by:
I'm trying to use the Const statement to define a group of constants. I would like different groups of constants, one for each language (such as english, spanish, etc.) Depending on a variable...
4
by: gabriel | last post by:
Greetings, I am working on a project and cannot choose the best way to achieve this : I got a method which returns an error code like this : DISK_FULL or PERMISSION_DENIED. Those are...
13
by: poison.summer | last post by:
Hello If I have an enum definition for instance typedef enum { F0 = 0, F1 = 1, F2 = 2, F3 =3
2
by: yawnmoth | last post by:
The PHP license states the following: 4. Products derived from this software may not be called "PHP", nor may "PHP" appear in their name, without prior written permission from group@php.net. ...
4
by: D. Yates | last post by:
Hi all, Is there a place in the .NET framework where simple time constants are defined? For example: How many days are there in a week? Hours in a day? Minutes in an hour? Seconds in a...
10
by: Steven W. Orr | last post by:
I saw this and tried to use it: ------------------><8------------------- const.py------------- class _const: class ConstError(TypeError): pass def __setattr__(self,name,value): if...
3
by: Steven W. Orr | last post by:
This is all an intro learning experience for me, so please feel free to explain why what I'm trying to do is not a good idea. In the Cookbook, they have a recipe for how to create global...
6
by: lazy | last post by:
hi, I have some constants defined in a php script say config.php. I want to use the variables there defined in other scripts. couple of questions regd that: 1. Is there an alternative to...
3
by: Microsoft | last post by:
Hi I have a c# program that continually runs 24/7 and performs a variety of tasks based on a timer. There is one routine that hangs every Saturday morning without fail. If I restart the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.