0

I am forward declaring a strongly typed enum in my header file. However, the include is not needed in the cpp even though I am defining a member function with it. Referencing this stackoverflow article this should not work. There are no other includes indirectly including the enum.

musicPlayer.h - Music::ID is being used to declare a member function which is legal

namespace Music
{
   enum class ID;
}

class MusicPlayer
{
public:
   load(Music::ID theme);
};

musicPlayer.cpp - Music::ID is being used to define a member function without being included which should be illegal

void MusicPlayer::Load(Music::ID theme)
{
} 
Community
  • 1
  • 1
user870130
  • 565
  • 1
  • 8
  • 16

1 Answers1

1

This is a new feature in C++11.
enums got rid of the need for integer #define constants, but still had some serious issues(like it allowed to compare with other enum types, which is meaningless).
So strongly typed enums (enum class) are introduced in C++11. The use of the word class is meant to indicate that each enum type really is different and not comparable to other enum types. Enum classes have advantages like better scoping and this feature for forward declaration that you mentioned. It is not the same as the class in your link.

Why is this useful??? Forward declarations are often about the physical layout of code on disk into different files or to provide opaque objects as part of an API. In the first case, where you care about the physical disk layout, using a forward declaration allows you to declare an enum type in the header file while putting specific values into the cpp file. This lets you change the list of possible enum values quite frequently without forcing all dependent files to recompile. In the second case, an enum class can be exposed as a type-safe but otherwise opaque value returned from one API function to be passed into another API function. The code using the API need not know the possible values the type can take on. Since the compiler still knows about the type, it can enforce that variables declared to work with that type are not confused with variables working with another type.

Refer here.

Following is an example:

enum class myStronglyTypedFloatEnum,myStronglyTypedCharEnum;

void myFunction(myStronglyTypedFloatEnum f,myStronglyTypedCharEnum c);

enum class myStronglyTypedFloatEnum : float {....}

enum class myStronglyTypedCharEnum : char {....}

This is of course meaningless as they are incomparable:

if(myStronglyTypedFloatEnum::f == myStronglyTypedCharEnum::c)  //NOT ALLOWED

Another example:

#include <iostream>
using namespace std;
enum class fruit;
void printFruit(fruit f); //Allowed :D
enum class fruit: int {MANGO = 1,APPLE = 2};
void printFruit(fruit f)
{
    if(f == fruit::MANGO) //f == 1 will give error: no match for ‘operator==’ (operand  
                          //types are ‘fruit’ and ‘int’)
        cout<<"fruit is mango";
    else
        cout<<"fruit is apple";
}
int main() {
    fruit myfruit=fruit::MANGO;
    printFruit(myfruit);
    return 0;
}
Sahil Sareen
  • 1,813
  • 3
  • 25
  • 40
  • The second case would apply to my use. If I understand the case where the object is opaque the include is never needed. Is this true of all types that can be forward declared? – user870130 Mar 23 '14 at 08:00
  • It is clear with enums. I was just following-up with whether this was true of all types that can be forward declared. – user870130 Mar 23 '14 at 08:14