2

I had enum class, say

enum class Enum{
   var1, var2;
}

Now I want to add some member which depends on parameter i.e var3(int). OK, It's not for enum, so I want to change it by regular class, but my goal is to leave old code(Enum::var1 as value of type Enum) possible to compile.

I tried to do it this way(let's temporary forgot about var3, it'll be static function):

class Enum{
    public:
        const static Enum var1 = Enum(1);
        const static Enum var2 = Enum(2);
    private:
        Enum(int v):v(v){
        }
    int v;
    //operator == using v
};

But it doesn't compile because Enum has incomplete type.
I can't declare it after class because it's in header so it'll not work with multiple cpp's. Besides, it's not great idea to have public constructor here.

Any thoughts?

RiaD
  • 46,822
  • 11
  • 79
  • 123
  • 2
    The biggest problem with this will be that you couldn't use `Enum::var1` where a constant expression is required. – Xeo Nov 03 '12 at 20:24
  • @Xeo1: will constexpr fix it? BTW, no need to use as constexpr(for now, maybe) – RiaD Nov 03 '12 at 20:26
  • 1
    No, since a class type can't be used as a, say, non-type template parameter. – Xeo Nov 03 '12 at 20:28
  • @Xeo: anyway, if I want add something that depends on parameter, I'll never have this advantage:), But thanks for useful comment. – RiaD Nov 03 '12 at 20:34
  • You wanted that everyone can use `Enum::var1` just the same as before. However, if `var1` is of type `Enum` now, and `Enum` is a class-type, and you used `Enum::var1` in a constant expression before, the code will not compile anymore. – Xeo Nov 03 '12 at 20:38

2 Answers2

1

Solution 1:

For the static variable problem: declare your static variables in the class declaration:

class Enum
{
    public:
        static const Enum var1;
        static const Enum var2;
        Enum(int v):v(v)
        {
        }
    private:
        int v;
        //operator == using v
};

Then, create a source file for this class, Enum.cpp, containing:

#include "Enum.h"
const Enum Enum::var1 = Enum(1);
const Enum Enum::var2 = Enum(2);

Solution 2:

If you want it to be header-only, you can use static variables instead of class variables:

class Enum
{
    public:
        Enum(int v):v(v)
        {
        }
    private:
        int v;
};

namespace Enumeration // It is not possible to name it 'Enum'
{
    // static => local to translation unit. No linking conflict
    static const Enum var1 = Enum(1);
    static const Enum var2 = Enum(2);
}

You can see a live example here. The only drawback is that you cannot use the name of the class for the namespace.

Synxis
  • 9,236
  • 2
  • 42
  • 64
  • It's cool, but I want to void it because I need to provide ONLY header to end-user – RiaD Nov 03 '12 at 20:25
  • Won't be able to use them where a constant expression is required. – Xeo Nov 03 '12 at 20:25
  • BTW doesn't compile with private ctor. Fixed it in your code. – RiaD Nov 03 '12 at 20:31
  • @RiaD, you can write initialization `var1` and `var2` in Enum.h, after class declaration. – Ruu Nov 03 '12 at 20:40
  • @Ruu and user will get compile error with two cpp's that include it. – RiaD Nov 03 '12 at 20:43
  • @RiaD, you can not initialize variables `static const ` where type is not `int`. `constexpr` – Ruu Nov 03 '12 at 20:52
  • @Riad Thanks for the fix. Now that I know you want a header-only solution, I've added a solution. See my edit. – Synxis Nov 04 '12 at 09:36
  • I thought about second solution. I think it's not so great but the best of possible, so I'm going to use it – RiaD Nov 04 '12 at 14:44
0

You can write a class like this:

class Enum
{
public
    enum NestedEnum : int
    {
        var1, var2
    };

    static NestedEnum var3;

    Enum(NestedEnum value) : value(value) { }

    operator NestedEnum() const { return value; }
private:
    NestedEnum value;
};

And anywhere else you can declare:

Enum::var3 = (Enum::NestedEnum)someIntegerVariable;
zahir
  • 1,298
  • 2
  • 15
  • 35