const defined as class member in another module

Discussion in 'C++' started by Christopher Pisz, Apr 25, 2013.

  1. I need to define the size of an array at compile time.

    The size I need to use is a static constant unsigned long which is a
    public class member in another library.

    The compiler complains that "expected constant size"

    If I try to use keyword extern, it compains that it is a class member
    and I cannot use keyword extern on it.

    I am not quite sure why the compiler does not think this is a constant
    which is defined at compile time or how I can use it in my array
    declaration. I could just allocate an array or use a std::vector, but
    one must learn when one comes across things he does not understand.

    Here is what I am trying

    // When I include the header from the library, it is linked via
    // compiler specific code.
    #include "OtherClass.h"

    int main()
    {
    unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
    return 0;
    }

    ----------------
    Then in the other library:

    In the OtherClass.h

    namespace OtherNamespace
    {
    MyClass
    {
    public:
    // REMOVED irrelevant code
    static const unsigned int MAX;
    };
    }

    --------------
    In the OtherClass.cpp

    namespace OtherNamespace
    {
    const unsigned int OtherClass::MAX_SIZE = 16;
    }
     
    Christopher Pisz, Apr 25, 2013
    #1
    1. Advertising

  2. Christopher Pisz

    K. Frank Guest

    Hello Christopher!

    On Thursday, April 25, 2013 6:34:06 PM UTC-4, Christopher Pisz wrote:
    > I need to define the size of an array at compile time.
    >
    > The size I need to use is a static constant unsigned long which is a
    > public class member in another library.
    >
    > The compiler complains that "expected constant size"
    >
    > If I try to use keyword extern, it compains that it is a class member
    > and I cannot use keyword extern on it.
    >
    > I am not quite sure why the compiler does not think this is a constant
    > which is defined at compile time or how I can use it in my array
    > declaration. I could just allocate an array or use a std::vector, but
    > one must learn when one comes across things he does not understand.
    >
    > Here is what I am trying
    >
    > // When I include the header from the library, it is linked via
    > // compiler specific code.
    > #include "OtherClass.h"
    >
    > int main()
    > {
    > unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
    > return 0;
    > }
    >
    > ----------------
    > Then in the other library:
    >
    > In the OtherClass.h
    >
    > namespace OtherNamespace
    > {
    > MyClass
    > {
    > public:
    > // REMOVED irrelevant code
    > static const unsigned int MAX;
    > };
    > }
    >
    > --------------
    > In the OtherClass.cpp
    >
    > namespace OtherNamespace
    > {
    > const unsigned int OtherClass::MAX_SIZE = 16;
    > }


    First comment:

    The way you currently have things structured, the compiler
    can't do what you want.

    (I am assuming that the use of "MAX" instead of "MAX_SIZE"
    in OtherClass.h is just a typo.)

    The file -- the so-called "translation unit" -- in which
    you are declaring myArray of size MAX_SIZE includes
    OtherClass.h. So when the array declaration is being
    compiled, the compiler could know that MAX_SIZE is a const
    int. But the actual value of MAX_SIZE doesn't appear in
    OtherClass.h, rather, it appears in OtherClass.cpp. The
    compiler doesn't know about OtherClass.cpp when it's
    compiling your first file (translation unit). (This is
    by design.)

    It's only at link time when you link your main program with
    the object file produced by compiling OtherClass.cpp that
    the value of MAX_SIZE becomes available to the overall program.

    What you want to do is very common, and the poor man's
    non-type-safe way to do it is to use a macro:

    #define MAX_SIZE 16

    But folks frown on that.

    C++11 let's you (I'm pretty sure) do the following as one
    of its new convenience features:

    OtherClass.h:

    MyClass {
    public:
    static const unsigned int MAX_SIZE = 16
    };

    Now OtherClass::MAX_SIZE is a nice, type-safe const int
    that can be used in your declaration of myArray in your
    main program.

    That is:

    #include "OtherClass.h"
    unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];

    is perfectly legal and does what you want.


    Good luck.


    K. Frank
     
    K. Frank, Apr 26, 2013
    #2
    1. Advertising

  3. Christopher Pisz

    K. Frank Guest

    Hi Paavo!

    On Friday, April 26, 2013 1:43:50 AM UTC-4, Paavo Helde wrote:
    > "K. Frank" <> wrote in news:2d93394f-1d20-4683-833a-
    > ...
    > > C++11 let's you (I'm pretty sure) do the following as one
    > > of its new convenience features:

    >
    > Nope, for integers this feature has been supported in all C++ versions,
    > precisely for the purpose of array declaration.


    Thank you for this correction. (C++11 extends this feature to
    non-integers and some other cases.)

    > > OtherClass.h:
    > >
    > > OtherClass {
    > > public:
    > > static const unsigned int MAX_SIZE = 16;
    > > };

    >
    > Note that a separate definition in some .cpp file
    >
    > const unsigned int OtherClass::MAX_SIZE;
    >
    > is formally still needed.


    I think (I'm a little foggy on exactly what the standard
    says) that the separate definition is only required by the
    standard if MAX_SIZE is used outside of constant expressions.

    > If not present, one may get linker errors
    > depending on the usage of this symbol, the compiler and its optimization
    > level.
    >
    > hth
    > Paavo


    Thanks.


    K. Frank
     
    K. Frank, Apr 26, 2013
    #3
  4. On 4/25/2013 6:34 PM, Christopher Pisz wrote:
    > I need to define the size of an array at compile time.
    >
    > The size I need to use is a static constant unsigned long which is a
    > public class member in another library.
    >
    > The compiler complains that "expected constant size"
    >
    > If I try to use keyword extern, it compains that it is a class member
    > and I cannot use keyword extern on it.
    >
    > I am not quite sure why the compiler does not think this is a constant
    > which is defined at compile time or how I can use it in my array
    > declaration. I could just allocate an array or use a std::vector, but
    > one must learn when one comes across things he does not understand.
    >
    > Here is what I am trying
    >
    > // When I include the header from the library, it is linked via
    > // compiler specific code.
    > #include "OtherClass.h"
    >
    > int main()
    > {
    > unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
    > return 0;
    > }
    >
    > ----------------
    > Then in the other library:
    >
    > In the OtherClass.h
    >
    > namespace OtherNamespace
    > {
    > MyClass


    I think you meant

    class OtherClass

    here...

    > {
    > public:
    > // REMOVED irrelevant code
    > static const unsigned int MAX;


    Use an enum instead.

    enum { MAX_SIZE = 16 };

    > };
    > }
    >
    > --------------
    > In the OtherClass.cpp


    And there is no need to add anything there...

    >
    > namespace OtherNamespace
    > {
    > const unsigned int OtherClass::MAX_SIZE = 16;
    > }


    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 26, 2013
    #4
  5. Christopher Pisz

    James Kanze Guest

    On Friday, April 26, 2013 3:44:58 AM UTC+1, K. Frank wrote:
    >
    > On Thursday, April 25, 2013 6:34:06 PM UTC-4, Christopher Pisz wrote:
    > > I need to define the size of an array at compile time.


    > > The size I need to use is a static constant unsigned long which is a
    > > public class member in another library.


    > > The compiler complains that "expected constant size"


    > > If I try to use keyword extern, it compains that it is a class member
    > > and I cannot use keyword extern on it.


    > > I am not quite sure why the compiler does not think this is a constant
    > > which is defined at compile time or how I can use it in my array
    > > declaration. I could just allocate an array or use a std::vector, but
    > > one must learn when one comes across things he does not understand.


    > > Here is what I am trying


    > > // When I include the header from the library, it is linked via
    > > // compiler specific code.
    > > #include "OtherClass.h"


    > > int main()
    > > {
    > > unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
    > > return 0;
    > > }


    > > ----------------
    > > Then in the other library:


    > > In the OtherClass.h


    > > namespace OtherNamespace
    > > {
    > > MyClass
    > > {
    > > public:
    > > // REMOVED irrelevant code
    > > static const unsigned int MAX;
    > > };
    > > }


    > > --------------
    > > In the OtherClass.cpp


    > > namespace OtherNamespace
    > > {
    > > const unsigned int OtherClass::MAX_SIZE = 16;
    > > }


    > First comment:


    > The way you currently have things structured, the compiler
    > can't do what you want.


    It could, and as it is worded, the standard actually says that
    it has to. A more accurate statement would be that a classical
    compiler couldn't do it, and the fact that the standard requires
    it is probably an error in the standard, since there is a
    definite intention that C++ not require anything beyond
    classical compiler technology (although as it stands, templates
    and inline functions also require a little be more).

    > (I am assuming that the use of "MAX" instead of "MAX_SIZE"
    > in OtherClass.h is just a typo.)


    > The file -- the so-called "translation unit" -- in which
    > you are declaring myArray of size MAX_SIZE includes
    > OtherClass.h. So when the array declaration is being
    > compiled, the compiler could know that MAX_SIZE is a const
    > int. But the actual value of MAX_SIZE doesn't appear in
    > OtherClass.h, rather, it appears in OtherClass.cpp. The
    > compiler doesn't know about OtherClass.cpp when it's
    > compiling your first file (translation unit). (This is
    > by design.)


    > It's only at link time when you link your main program with
    > the object file produced by compiling OtherClass.cpp that
    > the value of MAX_SIZE becomes available to the overall program.


    Most modern compilers have options which defer the actual code
    generation until link time. You can't really do effective
    optimization otherwise. For various historical reasons, this
    technology is only activated for optimization.

    > What you want to do is very common, and the poor man's
    > non-type-safe way to do it is to use a macro:


    > #define MAX_SIZE 16


    > But folks frown on that.


    To the point where I've never seen it in C++ code.

    > C++11 let's you (I'm pretty sure) do the following as one
    > of its new convenience features:


    > OtherClass.h:


    > MyClass {
    > public:
    > static const unsigned int MAX_SIZE = 16
    > };


    You don't need C++11; that works in C++98. In pre-standard C++,
    the usual solution was something like:

    class MyClass
    {
    public:
    enum { maxSize = 16 };
    // ....
    };

    Not perfect, because the actual type is an unnamed enum type,
    and not int, or size_t, or whatever. But it worked pretty well
    in practice. (Also, of course: unless maxSize is a macro, it
    won't be written in all caps.)

    --
    James
     
    James Kanze, Apr 27, 2013
    #5
  6. Christopher Pisz

    James Kanze Guest

    On Friday, April 26, 2013 6:43:50 AM UTC+1, Paavo Helde wrote:
    > "K. Frank" <> wrote in news:2d93394f-1d20-4683-833a-
    > :


    > > C++11 let's you (I'm pretty sure) do the following as one
    > > of its new convenience features:


    > Nope, for integers this feature has been supported in all C++ versions,
    > precisely for the purpose of array declaration.


    I've used C++ versions where it wasn't supported. It was
    introduced in C++98. The first "standard", but C++ was around
    before then.

    --
    James
     
    James Kanze, Apr 27, 2013
    #6
  7. On Apr 26, 7:06 am, "K. Frank" <> wrote:
    > Hi Paavo!
    >
    > On Friday, April 26, 2013 1:43:50 AM UTC-4, Paavo Helde wrote:
    > > "K. Frank" <> wrote in news:2d93394f-1d20-4683-833a-
    > > ...
    > > > C++11 let's you (I'm pretty sure) do the following as one
    > > > of its new convenience features:

    >
    > > Nope, for integers this feature has been supported in all C++ versions,
    > > precisely for the purpose of array declaration.

    >
    > Thank you for this correction.  (C++11 extends this feature to
    > non-integers and some other cases.)
    >


    From what I understand, even in C++11, the literals specified against
    non-integer members are not compile time constants. They specify the
    values to be given to the corresponding members upon initialization.

    The complete legalese is here:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2628.html

    - Anand
     
    Anand Hariharan, Apr 29, 2013
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,943
    Thomas Weidenfeller
    Oct 12, 2005
  2. Oodini
    Replies:
    1
    Views:
    1,842
    Keith Thompson
    Sep 27, 2005
  3. Javier
    Replies:
    2
    Views:
    622
    James Kanze
    Sep 4, 2007
  4. fungus
    Replies:
    13
    Views:
    948
    fungus
    Oct 31, 2008
  5. Replies:
    6
    Views:
    380
    Eric Sosman
    Oct 24, 2012
Loading...

Share This Page