0

There are several questions around concerning this topic (e.g. here and here). I am a bit surprised how lenghty the proposed solutions are. Also, I am a bit lazy and would like to avoid maintaining an extra list of strings for my enums. I came up with the following and I wonder if there is anything fundamentally wrong with my approach...

class WEEKDAY : public std::string{
    public: 
        static const WEEKDAY MONDAY() {return WEEKDAY("MONDAY");}
        static const WEEKDAY TUESDAY(){return WEEKDAY("TUESDAY");}
        /* ... and so on ... */
    private:
        WEEKDAY(std::string s):std::string(s){};
};

Still I have to type the name/string representation more than once, but at least now its all in a single line for each possible value and also in total it does not take much more lines than a plain enum. Using these WEEKDAYS looks almost identical to using enums:

bool isAWorkingDay(WEEKDAY w){
    if (w == WEEKDAY::MONDAY()){return true;}
    /* ... */
    return false;
}

and its straighforward to get the "string representation" (well, in fact it is just a string)

std::cout << WEEKDAY::MONDAY() << std::end;

I am still relatively new to C++ (not in writing but in understanding ;), so maybe there are things that can be done with enums that cannot be done with such kind of constants.

Community
  • 1
  • 1
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 3
    You cannot `switch()`. – timrau Dec 03 '14 at 16:20
  • 2
    Comparison becomes time-consuming. – timrau Dec 03 '14 at 16:21
  • 2
    a) You have many useless functions. More overhead than enums. b) You´re using strings instead of numeric IDs. Much more overhead (memory+time). c) Things like translations are very hard with your approach. d) ... – deviantfan Dec 03 '14 at 16:21
  • @deviantfan a) What useless functions do you mean? All the stuff inherited from string? b) if i need a string representation this is not overhead c) why is this any different with my approach than with any other? and btw enums dont offer any way to "translate" d) would be interesting to hear also you other comments.... – 463035818_is_not_an_ai Dec 03 '14 at 16:26
  • @tobi303 a) `static const WEEKDAY MONDAY() {...}` is a function. You don´t need 7 functions for the week. – deviantfan Dec 03 '14 at 16:55
  • b) If you do hundred things with weekday data (compare them, sort 1000 saved weekdays, etc.etc.), strings are a gigantic overhead compared to int´s (0 sunday, ...). And an enum instance is essentially a int, just with pretty names *in the code* (only there, not in the user interface). And if you need to print out a weekday to the user, after doing some things with the int, make the conversion then, right before printing it. The enum won´t offer a benefit there, you still have to convert enum elements to readable strings manually. Strings will help for this case, but are worde in anything else. – deviantfan Dec 03 '14 at 16:55
  • c) Hard-coded strings in the code (or worse, even in own functions) are impossible to change without recompiling. With everything ID-like like enums (and conversion right before printing) you could load the string representations of a external language file etc. Not possible with your approach. – deviantfan Dec 03 '14 at 16:57

1 Answers1

1

You could use the preprocessor to avoid duplicating the names:

#define WEEKDAY_FACTORY(DAY) \
    static const WEEKDAY DAY() {return WEEKDAY(#DAY);}

WEEKDAY_FACTORY(MONDAY)
WEEKDAY_FACTORY(TUESDAY)
// and so on

Whether the deduplication is worth the obfuscation is a matter of taste. It would be more efficient to use an enumeration rather than a class containing a string in most places; I'd probably do that, and only convert to a string when needed. You could use the preprocessor to help with that in a similar way:

char const * to_string(WEEKDAY w) {
    switch (w) {
        #define CASE(DAY) case DAY: return #DAY;
        CASE(MONDAY)
        CASE(TUESDAY)
        // and so on
    }
    return "UNKNOWN";
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644