3

Following the C++ enum pattern I already described here, I was trying to do a similar thing but this time the sequence of values I want to use is not comprehended of continuous integer numbers.

The code is obviously wrong:

class Rotations
{
    enum PossibleIndexes
    {
        ZERO,
        PLUS180,
        PLUS90,
        MINUS90
    };


    enum PossibleValues
    {
        ZERO= 0,
        PLUS180= 180,
        PLUS90= 90,
        MINUS90= -90
    };

    static int Count() { return MINUS90 + 1; }

    static PossibleValues Default(){ return ZERO; }
};

as there will be conflicts between elements inherent of the two enums.

So my question is: What is the best approach to implement a fixed number of hardcoded Rotations{0, 180, 90, -90} which has also a Default and a Count functionality?

Community
  • 1
  • 1
sergiol
  • 4,122
  • 4
  • 47
  • 81

3 Answers3

4

You can always keep a static std::initializer_list containing all possible values

namespace PossibleValues
{
    enum Type
    {
        ZERO= 0,
        PLUS180= 180,
        PLUS90= 90,
        MINUS90= -90
    };

    constexpr auto Values = {ZERO, PLUS180, PLUS90, MINUS90};
    size_t Count() { return Values.size(); }
    Type Default() { return *begin(Values); }
}

This approach will have the added bonus of being able to iterate of the values of the enum in a for-loop

Note: I wish the compiler could generate all that code though, at least for enum class

KABoissonneault
  • 2,359
  • 18
  • 17
  • @AdrianoRepetti Yeah, too bad the other post is kind of old, so I don't think it's appropriate to post my answer there. Hopefully Googlers will see my answer too! – KABoissonneault May 27 '15 at 12:58
  • Why not? There is also a specific badge for that (if I remember well)! Especially if you expand and change your answer little bit to be more specific to that post! – Adriano Repetti May 27 '15 at 13:05
  • Visual studio does not compile that code. IntelliSense gives: "Error: cannot deduce 'auto' type". And when compiling, I get more errors in that same line: error C2059: syntax error : '{' and also error C2334: unexpected token(s) preceding '{'; skipping apparent function body – sergiol May 27 '15 at 13:29
  • Hmm, yeah from my experience Visual Studio is not too good with the whole Uniform Initialization syntax. Try replacing auto with std::initializer_list first, and if it doesn't work, try an std::vector – KABoissonneault May 27 '15 at 13:32
  • Update to my previous comment: I replaced auto by std::initializer_list. IntelliSense gives "Error: namespace "std" has no member "initializer_list". And when compiling. I get error C2039: 'initializer_list' : is not a member of 'std' error C4430: missing type specifier - int assumed. Note: C++ does not support d error C2146: syntax error : missing ';' before identifier 'ValuesOfPossibleValues ' error C2059: syntax error : '{' error C2334: unexpected token(s) preceding '{'; skipping apparent function body – sergiol May 27 '15 at 13:36
  • Try including . This header is usually automatically included when you use brace initialization with auto, but if you write the type explicitly, you might have to include it – KABoissonneault May 27 '15 at 13:38
  • I tried #include and is still fails to parse. IntelliSense gives: "Error: a member of type "const std::initializer_list" cannot have an in-class initializer" and when compiling I get: error C2059: syntax error : '{' error C2334: unexpected token(s) preceding '{'; skipping apparent function body – sergiol May 27 '15 at 14:07
  • I get the same errors if I replace std::initializer_list by std::vector. – sergiol May 27 '15 at 14:22
  • Remove the const then. It was kind of pointless since initializer_lists are immutable anyway – KABoissonneault May 27 '15 at 14:23
  • Removed the const, and still get the same error, both for vector and for initializer_list. – sergiol May 27 '15 at 14:28
  • I Tried static const std::initializer_list ILCints = { 0, 180, 90, -90 }; static std::initializer_list ILints = { 0, 180, 90, -90 }; static const std::vector VCints = { 0, 180, 90, -90 }; static std::vector Vints = { 0, 180, 90, -90 }; and none of them worked . I wonder what types can support in-class initializers. May be only the raw C arrays? – sergiol May 27 '15 at 14:38
  • Alright, managed to get it working here http://ideone.com/HDpjXC The constexpr has to be removed for Visual Studio 2013 though, but it worked fine even without constexpr. – KABoissonneault May 27 '15 at 14:49
  • I tried the approach of your last edit and it did not work, because I am inside another class and I cannot declare a namespace inside it. – sergiol May 27 '15 at 15:00
  • Can you try fiddling with it until you find a solution that works for you? – KABoissonneault May 27 '15 at 15:03
  • It is what I have been doing. Now, I tried to have the namespace outside of the class, with http://ideone.com/dPn3cw and Visual Studio still gave "error C2078: too many initializers" on the 'auto' line. – sergiol May 27 '15 at 15:14
1

Disclaimer: I am mentioning an open-source library that I recently published.

You may want to look at Better Enums. It will save you from having to repeat anything.

#include <enum.h>
ENUM(Rotations, int, ZERO = 0, PLUS180 = 180, PLUS90 = 90, MINUS90 = -90)

You could then access the number of constants as

Rotations::_size

There is currently no built-in way of declaring a default value. However, the default constructor is currently private, so you would be forced to provide a value when creating a Rotations value. There is a syntactically "nice" way to do this shown here – look at how invalid is defined using a template. It might be complete overkill for your needs. If you try this library and have any feedback concerning default values, please let me know.

I should note that the count and default value are generated at compile time.

antron
  • 3,749
  • 2
  • 17
  • 23
  • Ahh, this looks like the kind of stuff I want the compiler to do. Good to see someone has already done the work I was about to do. – KABoissonneault May 27 '15 at 15:47
0

Due to the limitations of Visual C++ 2010 Compilation Toolkit (not fully C++11 compliant), I had to surrender myself to inferior approaches.

The post at https://stackoverflow.com/a/15961043/383779 also suggested me an interesting approach for getting the values.

class Rotations
{
public:
    typedef enum
    {
        ZERO= 0,
        PLUS180= 180,
        PLUS90 = 90,
        MINUS90 = -90
    }PossibleValues;

    static const PossibleValues PossibleValuesCollection(int index) {
        static const PossibleValues values[] = { ZERO, PLUS180, PLUS90, MINUS90 };

        return values[index];
    }

    static int Count() { return 4; }
    static PossibleValues Default(){ return ZERO; }
};
Community
  • 1
  • 1
sergiol
  • 4,122
  • 4
  • 47
  • 81