-1

I am trying to use the constant int SIZE that is declared in the TaxConstants.hpp namespace TAXCONSTANTS in other places in my project. When I try to compile, I get "undefined reference to 'SIZE' everywhere that SIZE is referenced.

file TaxConstants.hpp

#ifndef TaxConstants_hpp
#define TaxConstants_hpp


namespace TAXCONSTANTS
{
     extern const int SIZE = 4; // I have tried with and without extern
}

#endif //TAXCONSTANTS_HPP

main.cpp

#include <iostream>
#include "TaxConstants.hpp"
using namespace std;
using namespace TAXCONSTANTS;

int main()
{
extern const int SIZE;

// This is a struct defined in another file. It is a sample of my use for SIZE. I left out the #include above to simplify things. 
taxPayer payers[SIZE];  

//More code

return 0;
}

Additional info: this is a school project and my teach has made it a requirement to declare constants in the file TaxConstants.hpp in the namespace TAXCONSTANTS.

There are 5 files in total, the file with my functions is having the same undefined reference to SIZE error.

I have spent hours looking up similar explanations on the extern function and namespaces, but most of the suggestions are against doing this in the first place an offer another solution. I, unfortunately can not use them. Other errors people had were getting "multiple decorations" which I am not having.

EDIT

See Brians explanation below for better detail.

What I needed to do was define

const int SIZE = 4;

within the TaxConstants.hpp file in namespace TAXCONSTANTS.

Then remove 'extern const int SIZE;' from my main file and instead reference SIZE by TAXCONSTANTS::SIZE everywhere I wanted to use size.

This is basic namespace stuff that I completely forgot about.

Community
  • 1
  • 1
Bow
  • 3
  • 2
  • 4
  • Possible duplicate: [Why does “extern const int n;” not work as expected?](http://stackoverflow.com/questions/14894698/why-does-extern-const-int-n-not-work-as-expected) – Thomas Matthews Feb 07 '17 at 02:21
  • I don't believe this has anything to do with namespaces, but the issue of `extern const`. – Thomas Matthews Feb 07 '17 at 02:21
  • You can see other posts using the search terms [stackoverflow c++ extern const](https://www.google.com/search?q=stackoverflow+c%2B%2B+extern+const&ie=utf-8&oe=utf-8) – Thomas Matthews Feb 07 '17 at 02:23
  • Thanks everyone. I finally figured it out right before checking back here. As Brian and AnT both state below, I was going about this wrong. Their explanations are better than I can write. I will add my resolution to the question. – Bow Feb 07 '17 at 02:41

2 Answers2

2

If you define SIZE without the extern keyword, it will have internal linkage since it is const. You can refer to it inmain.cpp as TAXCONSTANTS::SIZE. This is recommended since the compiler will be able to inline the value wherever SIZE is used.

If you define SIZE with the extern keyword, it will have external linkage and it should not be in a header, unless you want multiple definition errors. You should instead define it in a .cpp file which will be linked into the rest of the program. In this case there will be only one copy of SIZE in the entire program. You should avoid this approach (preferring instead the approach without extern) unless for some reason you actually need to have only one copy of SIZE in the entire program.

In both cases, SIZE will be a member of the TAXCONSTANTS namespace.

Your attempt to redeclare SIZE inside main does not do what you think it does! The following inside main:

extern const int SIZE;

actually has the effect of declaring SIZE in the global namespace. Since there is no definition of SIZE in the global namespace, you get undefined reference errors at link time. It is not the correct way to refer to the SIZE variable defined in TAXCONSTANTS.

Sebastian Brosch
  • 42,106
  • 15
  • 72
  • 87
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Thank you, I figured it out right before checking back here. You were write, I was going about it wrong and should have used TAXCONSTANTS::SIZE instead. – Bow Feb 07 '17 at 02:42
0

Multiple problems with the entire approach.

  1. Your

    extern const int SIZE;
    

    in main is a declaration of const int object SIZE from global namespace - ::SIZE. This SIZE has absolutely nothing to do with your TAXCONSTANTS::SIZE. Such global ::SIZE object is not defined in your program, which is why you get "undefined reference" error.

    Since you already declared TAXCONSTANTS::SIZE in the header file, you don't need to redeclare SIZE again in main. Why are you doing this?

    Just remove the declaration from main and use SIZE from TAXCONSTANTS either through using namespace TAXCONSTANTS or by specifying a qualified name TAXCONSTANTS::SIZE.

  2. The declaration you have in the header file is actually a definition. Including this header file into multiple translation units will result in another error: multiple definitions of the same object with external linkage.

    If you want to declare a global constant object, you have to keep a mere non-defining declaration in the header file

    namespace TAXCONSTANTS
    {
      extern const int SIZE; // declaration, not definition
    }
    

    and move the definition into one of implementation files

    namespace TAXCONSTANTS
    {
      extern const int SIZE = 4; // definition
    }
    
  3. However, it appears that you are planning to use this constant as an Integral Constant Expression (as array size in array declaration). An extern const int constant declared without an initializer will not work for that purpose.

    Just forget about extern and declare a normal constant with internal linkage in the header file

    namespace TAXCONSTANTS
    {
      const int SIZE = 4; // definition with internal linkage
    }
    

    and then just use in everywhere it is needed

    using namespace TAXCONSTANTS;
    
    int main()
    {
      taxPayer payers[SIZE];  
      ...
    }
    

    or

    // no 'using namespace TAXCONSTANTS;'
    
    int main()
    {
      taxPayer payers[TAXCONSTANTS::SIZE];  
      ...
    }
    
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Thank you, I was supposed to write it like TAXCONSTANTS::SIZE as you mentioned. – Bow Feb 07 '17 at 02:43