Thread: global integral constants

  1. #1
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597

    global integral constants

    Often in a project, there is a need for some global integral constants (which may be used as array sizes).

    For example, in a recent project, I was working on a hardware emulator which has a fixed number of analog inputs. so in Globals.h I had

    Code:
    namespace NSP // platform name
    {
    
        static const unsigned int NUM_INPUTS = 20;
    
    } // namespace NSP
    but it was mentioned to me that static used in this fashion is deprecated, and the preferable solution is to use an unnamed namespace. so then we have
    Code:
    namespace NSP // platform name
    {
    
        namespace // anon
        {
            const unsigned int NUM_INPUTS = 20;
        } // namespace anon
    } // namespace NSP
    and ye standard gods were appeased.

    but after a bit of unrelated research today, I've discovered that unnamed namespaces in headers are a no-no as they can violate ODR.

    so what's the correct way? I don't like the "enum-hack" (for one thing, you can't take the address of it if you need to).
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    but after a bit of unrelated research today, I've discovered that unnamed namespaces in headers are a no-no as they can violate ODR.
    Where was that? I don't think it would be a problem if you had inclusion guards.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Why do you need static or an unnamed namepsace for that use? Usually static is for constants put into a source file (and similarly the unnamed namespace). For those you want to be global, wouldn't you add an extern declaration in the header and a non-static definition in the source?

    >> I don't think it would be a problem if you had inclusion guards.
    A separate constant would be created for each compilation unit that includes that header.

  4. #4
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    Quote Originally Posted by Daved
    Why do you need static or an unnamed namepsace for that use? Usually static is for constants put into a source file (and similarly the unnamed namespace). For those you want to be global, wouldn't you add an extern declaration in the header and a non-static definition in the source?
    if you have an extern you can't use the constant as an array size attribute.
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    It can happen if there is little care in the definition of those unamed namespaces. Names defined inside a unamed namespace are local to the file only. We cannot span unamed namespaces across files as we do with regular names.

    Consider somefile.h:

    Code:
    namespace {
        int a;
    }
    and anotherfile.h

    Code:
    namespace {
        int a;
    }
    now... consider source.cpp

    Code:
    #include "somefile.h"
    #include "anotherfile.h"
    int main() {
       // which int a?
    }
    The solution can be one of two, from what I can see:

    Declare unamed namespaces within named namespaces taking advantage of the fact we can nest namespaces.

    Or remember that namespaces expect object definitions. Not necessarily declarations. It is at the object definition time that the object will be associated with the namespace. So it's possible to declare the object somewhere and define it somewhere else inside a namespace. This basically means, creating the unamed namespace in source files.

    EDIT: Hmm... at second thought I'm not that sure of this second option.
    Last edited by Mario F.; 09-14-2006 at 04:48 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Quote Originally Posted by Mario F.
    Declare unamed namespaces within named namespaces taking advantage of the fact we can nest namespaces.
    That's what ChaosEngine is doing. So does that mean that the code as given doesn't violate ODR?
    Code:
    namespace NSP // platform name
    {
    
        namespace // anon
        {
            const unsigned int NUM_INPUTS = 20;
        } // namespace anon
    } // namespace NSP
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Well, no. Because you are in control of the namespace. It's yours. You should know your namespace members. As such you can know if you have already defined an object with the same name inside that namespace and that is within scope of the redefinition.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> if you have an extern you can't use the constant as an array size attribute.

    I see. I don't know the answer. However, doesn't a static const in a header violate ODR just as much as the constant in the unnamed namespace in a header? I don't know if there is a way to do it that doesn't create multiple definitions. Otherwise, how would the compiler know the size of the array in the different compilation units?

    Perhaps create an enum and an extern const in the header, then use the enum for array sizes and define the const equal to the enum in a source file so you can take its address.

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    > I don't know if there is a way to do it that doesn't create multiple definitions.

    There is nothing wrong with namespaces, Daved.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    So ChaosEngine's anonymous namespace code is correct? [edit] Assuming there isn't another variable in the namespace called NUM_INPUTS. [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Yes. That's my opinion. Assuming he owns the NSP namespace (he is the implementator of that namespace).

    If he does, he controls what names are declared and when. The unamed namespace is controled by an outer named namespace. Named namespaces can span across several files (unamed ones can't). It's that simple. It is thus safe to declare that namespace in an header file. Of course, ChaosEngine just needs to make sure he's only defining the variable once within the NSP namespace. But he can create as many unamed namespaces with that same variable exactly as he wants in other files. They don't span across files.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  12. #12
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    cheers, guys. that pretty much confirms what I thought, just wanted to get a few other opinions on it.
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    but after a bit of unrelated research today, I've discovered that unnamed namespaces in headers are a no-no as they can violate ODR.
    So I guess this meant to not use anonymous namespaces in the global namespace?
    Code:
    // header.h
    #ifndef HEADER_H
    #define HEADER_H 1
    
    namespace {
        const int x = 0;
    };
    
    #endif
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> There is nothing wrong with namespaces, Daved.
    Falcons have no teeth, Mario F.

    If you use an unnamed namespace there will be multiple definitions of the constant in the program. It will compile and link correctly, but different compilation units will get different results if they take the address of the constant. I was under the impression that this is what was trying to be avoided.

    Putting the unnamed namespace inside of a named namespace has no effect on the situation, it is irrelevent to the issue.

    Using the enum and extern does work, and provides a single address for each compilation unit.

    >> So I guess this meant to not use anonymous namespaces in the global namespace?
    No, unnamed namespaces in header files generally defeats the purpose of them. Unnamed namespaces in the global namespace are the normal way of using them.

  15. #15
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Yup. That is bad. Because unnamed namesapces defined globally basically put all their members on the global scope. This is so because unnamed namespaces place their member names at the scope the unnamed namespace was declared.

    Code:
         int i;   // global i
         namespace {
             int i; // namespace i
         }
         i = 12;  // error here. It's ambiguous.
    Note that the error is only caught when the variable is used. Which makes this type of error a nasty one to debug.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. basic question about global variables
    By radeberger in forum C++ Programming
    Replies: 0
    Last Post: 04-06-2009, 12:54 AM
  2. Best way to avoid using global variables
    By Canadian0469 in forum C++ Programming
    Replies: 7
    Last Post: 12-18-2008, 12:02 PM
  3. Global objects and exceptions
    By drrngrvy in forum C++ Programming
    Replies: 1
    Last Post: 09-29-2006, 07:37 AM
  4. Initalizing global variables to constants
    By maxhavoc in forum C Programming
    Replies: 6
    Last Post: 06-21-2006, 11:25 AM
  5. defining and using a global class
    By cjschw in forum C++ Programming
    Replies: 4
    Last Post: 03-05-2004, 09:51 PM