3

In my project, I have a header file containing the following lines.

extern enum class options {alpha, beta, gamma, theta};
extern options P1, P2;

Compilation gives me

error: a storage class can only be specified for objects and functions

Why?
How can I rectify this?

Compiler: GCC 9.2.0

PalLaden
  • 635
  • 6
  • 17
  • `extern` means the thing I am applied to is defined somewhere else. How would you apply that to a definition? – NathanOliver Apr 08 '21 at 15:47
  • 1
    Regarding your edit of *I wish to spilt it up into a declaration in the .h file and a definition in a .cpp*. I believe [this](https://stackoverflow.com/a/1280969/4342498) or [this](https://stackoverflow.com/a/11632184/4342498) have your answer. – NathanOliver Apr 08 '21 at 15:59
  • See also [What is the difference between a definition and a declaration](https://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration) – Wyck Apr 08 '21 at 16:31

2 Answers2

2

extern is applied to variables to specify that they have external linkage. What you have is not a variable but an enum definition, therefore extern cannot be applied to it.

What you can do is apply extern to variables at file scope of the enum type.

For example, your header file would have:

enum options {alpha, beta, gamma, theta};

extern options myoption;

And in one source file you would have:

options myoption;
dbush
  • 162,826
  • 18
  • 167
  • 209
1

There's no storage associated with an enum class definition. So it doesn't make sense for it to be marked as extern.

A variable whose type is an enum class, on the other hand, can certainly be extern because there's storage associated with a variable to hold the value of that variable. The location of this storage is something that the linker must ultimately work out.

It makes sense to know of the existence of a variable without being responsible for designating storage for it at link time. This is how you get global variables. For example:

main.cpp

int foo = 5; // declaration and definition together.

other.cpp

extern int foo; // declaration only, (external definition still required elsewhere)
// but you can now use `foo` in this file. e.g.:
int examineFoo() {
  return foo;
}

This is also useful if you want to provide a declaration of a global variable in a header file. For example:

main.cpp

#include "foo.h"
int foo = 5;

foo.h

extern int foo;

other.cpp

#include "foo.h"
int examineFoo() {
  return foo;
}

It's okay to encounter both the extern declaration and the definition in the same file. e.g.:

extern int foo;
int foo = 5;

To fix your problem

To fix exactly the example you provided, you can remove extern from the enum class definition, where it does not make sense to have it.

enum class options {alpha, beta, gamma, theta};
extern options P1, P2;

Remember that some non-extern definition of those variables P1 and P2 will be required in another module in order for your program to link if you make use of them.

For you, you probably want the class to be defined in a header, along with an extern declaration of any global variables (yuck) you want in your program.

options.h

enum class options {alpha, beta, gamma, theta};
extern options P1, P2;

options.cpp

#include "options.h"
options P1 = options::alpha, P2 = options::beta;

In options.cpp you include options.h to get the definition of the enum class. It also came with an extern definition of the global variables P1 and P2, which wasn't strictly necessary as they are going to be defined in this file anyway, but it's not illegal to do it.

other.cpp

#include "options.h"
options examineOptionP1() {
   return P1;
}

other.cpp is aware of the class definition for options and is aware of extern declarations of P1 and P2.

Wyck
  • 5,985
  • 4
  • 34
  • 44