0

In Java I can define enum constants that have multiple members and member functions, yet do not provide public access to the enum constructor so that the client code cannot create enums in addition to those that are already defined.

I would like to emulate this behavior in C++, and tried to do so like this:

// Card ranks of a 52-card deck
class _CardRank {
public:
    _CardRank(int val, char repr) : val{ val }, repr{ repr } {};

    int get_val() { return val; };
    char get_repr() { return repr; };

private:
    int val;
    int repr;
};

namespace CardRank {
    const _CardRank C_2(0, '2');
    const _CardRank C_3(1, '3');
    const _CardRank C_4(2, '4');
    const _CardRank C_5(3, '5');
    const _CardRank C_6(4, '6');
    const _CardRank C_7(5, '7');
    const _CardRank C_8(6, '8');
    const _CardRank C_9(7, '9');
    const _CardRank C_T(8, 'T');
    const _CardRank C_J(9, 'J');
    const _CardRank C_Q(10, 'Q');
    const _CardRank C_K(11, 'K');
    const _CardRank C_A(12, 'A');
}

This gives me the scoped constants I am looking for, the client code would however still be able to create new constants. Is there any idiomatic solution to this, or is this design pattern not valid for C++?

J. Grohmann
  • 391
  • 1
  • 6
  • 15
  • On an unrelated note, all symbols beginning with an underscore followed by an upper-case letter (Like `_CarRank`) is reserved in all scopes and contexts, and you should not define such symbols yourself. See e.g. [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) – Some programmer dude Apr 16 '21 at 08:19
  • 1
    What about something like `static const std::map CarRank = {{0, '2'}, {1, '3'}};`? It's constant and you cannot extend it with new elements. – vahancho Apr 16 '21 at 08:23

2 Answers2

2

You might use class as namespace to allow friendship:

class CardRank
{
private:
    friend class CardRankNamespace;
    constexpr CardRank(int val, char repr) : val{ val }, repr{ repr } {}

public:
    int get_val() const { return val; }
    char get_repr() const { return repr; }
private:
    int val;
    int repr;
};

class CardRankNamespace
{
public:
    static constexpr CardRank C_2{0, '2'};
    // ...
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

Closest solution I can think of is anonymous structure:

namespace MyEnum
{
    constexpr struct
    {
        const int val;
        const char *rep;
    } Enum1{1, "1"},
      Enum2{2, "2"},
      Enum3{3, "3"};
}
ostojan
  • 608
  • 1
  • 7
  • 17