1

Suppose I have a MessageBox class along the following lines:

class MyMessageBox
{
public:
    enum Priority {
        Prior_Dialog,
        Prior_Warning,
        // ...
    };

    enum Icon {
        Icon_Question,
        Icon_Exclamation,
        // ...
    };

    enum Button {
        Button_Yes,
        Button_No,
        Button_Cancel,
        // ...
    };

    static void Show(Priority pPriority, Icon pIcon, Button pButton1, Button pButton2);

    // ...
};

Now, if I want to throw up a messagebox, I have to type out MyMessageBox:: for every single identifier:

MyMessageBox::Show(MyMessageBox::Prior_Dialog, MyMessageBox::Icon_Question, MyMessageBox::Button_Yes, MyMessageBox::Button_No);

Ideally, I'd like some non-macro solution that will allow source files that #include "MyMessageBox.h" to omit the MyMessageBox:: qualifications everywhere. Is this possible?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
suszterpatt
  • 8,187
  • 39
  • 60

5 Answers5

7

Yes, and quite simple. If you don't want the enums inside the class, well... don't define them inside the class.

enum Priority {
    Prior_Dialog,
    Prior_Warning,
    // ...
};

enum Icon {
    Icon_Question,
    Icon_Exclamation,
    // ...
};

enum Button {
    Button_Yes,
    Button_No,
    Button_Cancel,
    // ...
};

class MyMessageBox
{
public:
    static void Show(Priority pPriority, Icon pIcon, Button pButton1, Button pButton2);
// ...
};
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
4

Maybe it would be convenient if the enumerations and the class are declared in the separate namespace (i.e. enumerations should be declared outside the class) just not to pollute the global namespace.

namespace MessageBoxUtils {

enum Priority {
    Prior_Dialog,
    Prior_Warning,
    // ...
};

enum Icon {
    Icon_Question,
    Icon_Exclamation,
    // ...
};

enum Button {
    Button_Yes,
    Button_No,
    Button_Cancel,
    // ...
};

class MyMessageBox
{
public:
    static void Show(Priority pPriority, Icon pIcon, Button pButton1, Button pButton2);

    // ...
};

} // namespace MessageBoxUtils

Client code (some cpp file):

#include ...

using namespace MessageBoxUtils;

...

void SomeClass::Foo()
{
    MyMessageBox::Show(Prior_Dialog, Icon_Question, ...);
}
  • Follow-up question: I know putting `using` declarations in header files is a big no-no in general, but in this case, would it be acceptable to put `using MessageBoxUtils` directly into `MyMessageBox.h`, so that it's automatically present in every source file that uses it? – suszterpatt Aug 14 '12 at 19:17
  • @suszterpatt, `using namespace` statement in **header files** is a bad smell, but it is good in implementation (cpp) files. See http://stackoverflow.com/questions/4872373/why-is-including-using-namespace-into-a-header-file-a-bad-idea-in-c – Sergey Vyacheslavovich Brunov Aug 14 '12 at 19:29
1

If you want to define the enums outside the class, and you alsio want to avoid repetitions and avoid the risk of enum names clashes, consider also the C++11 enum class possibility:

Re-elaborating Luchian Grigore sample

enum class Priority {
    Dialog,
    Warning,
    // ...
};

enum class Icon {
    Question,
    Exclamation,
    // ...
};

enum class Button {
    Yes,
    No,
    Cancel,
    // ...
};

You are now forced to use the enums by explicitly qualifying them, like Button::Yes, Icon::Question etc., and you are also forced to cast explicitly to int (no implicit conversions exist)

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
0

You cannot "import" identifiers into the global namespace by means of the using keyword:

using MyMessageBox::Prior_Dialog; // won't work

(The first glance on the documentation misled me: http://msdn.microsoft.com/en-us/library/was37tzw%28v=vs.80%29.aspx)

Still, I would recommend leaving the enums where they belong -- in the MessageBox class. This avoids confusion and ambiguities -- someone else could define the same enum item but assign it a different value, leading to a compilation error.

Alternatively, you could change the class into a namespace, and then "load" identifiers (or even the whole namespace, if you wish), using using.

Other possible shortcuts include:

  • typedefing the enum inside the MessageBox class to a short convenient identifier and use this as qualification (hacky)

  • Copying individual constants into your namespace as they are required (cumbersome)

  • ...?

krlmlr
  • 25,056
  • 14
  • 120
  • 217
0

Another option is to put your enum into completely different namespace related to your widget. Qt libraries do so for example. They put lots of enum in Qt namespace instead of putting them in the specific classes

Andrew
  • 24,218
  • 13
  • 61
  • 90