2015-03-02 36 views
4

有没有办法改变枚举如何设置其常量的值?通常它会递增1,但我想要应用其他规则。典当这会工作应用关于如何递增枚举的规则

enum (<<=1) { 
a = 1,//0b001 
b,//0b010 
c//0b100 
} 

有没有办法在C++中做到这一点?

+0

感谢你的快速回答。实际上我想创建很多常量,这些常量在开发期间可能会发生变化,所以我将不得不一直改变它。不幸的是,这不是一个很好的解决方案,在这种情况下手动执行它 – neophoenix 2015-03-02 11:41:44

+0

我会这样做我会把枚举放在一个单独的文件中,并创建一个生成器(例如在Python中)根据您的规范创建枚举。 – bolov 2015-03-02 11:45:37

回答

4

不会自动的,但也可以手动指定每个值

enum X { 
    a = 0x01, 
    b = 0x02, 
    c = 0x04 
}; 
+2

@sharptooth我不明白你怎么可以用模板做到这一点。如果你想表现出方式,我会非常感兴趣。 – bolov 2015-03-02 11:43:22

+1

@no,因为我不知道如何模拟enum或enum的值。 – bolov 2015-03-02 11:49:38

+1

@sharptooth请以实例支持您的陈述。 – CinCout 2015-03-02 11:54:39

1

为你得到(枚举其基本上是一个字内的标志)是使用两个枚举,一个用于位的具体实例中的一种常见方法指数以及实际的位值第二枚举:

enum { 
    b_a,    // 0 
    b_b,    // 1 
    b_c,    // 2 
    b_d,    // 3 
}; 

enum { 
    a = 1 << b_a, // 1 
    b = 1 << b_b, // 2 
    c = 1 << b_c  // 4 
    d = 1 << b_d  // 8 
}; 

这不是理想的,我知道,但它避免了明确的字面常量。一些糟糕的东西可以用宏来隐藏,你可能认为它不是一件好事。

3

你可以使用模板元编程自动完成这一转变过程:

template<int by> 
struct OneShlBy { 
    enum { Value = OneShlBy<by - 1>::Value << 1 }; 
}; 

template<> 
struct OneShlBy<0> { 
    enum { Value = 1 }; 
}; 

enum X { 
    a = OneShlBy<0>::Value, 
    b = OneShlBy<1>::Value, 
    c = OneShlBy<2>::Value 
}; 
+2

如果必须对每个常量应用OneShlBy,直接使用移位运算符“a = 1,b = 1 << 1,...”而不是模板会更容易吗? – neophoenix 2015-03-02 12:46:57

+1

@neophoenix将会更容易,直到你种植一个愚蠢的错字,然后寻找它一段时间。 – sharptooth 2015-03-02 12:57:20

0

什么你在做工作完全正常:

#include <iostream> 

enum x { 
    a = 0b001 
, b = 0b010 
, c = 0b100 
}; 

int main() 
{ 
    std::cout << x::a << '\n'; 
    std::cout << x::b << '\n'; 
    std::cout << x::c << '\n'; 
} 

注:这只是标准C++ 14引入了二进制文字。

否则,你可以使用移位运算符来指定位的位置:

enum x { 
     a = 1 << 0 
    , b = 1 << 1 
    , c = 1 << 2 
}; 

如果你正在寻找节省一些维护工作在以前来定义每个enum另一种可能性定义enums

enum x { 
     a = 1 
    , b = a << 1 
    , c = b << 1 
    , d = c << 1 
    , e = d << 1 
}; 

这意味着您可以相对无痛地在中间添加元素:

enum x { 
     a = 1 
    , b = a << 1 
    , z = b << 1 // new element added 
    , c = z << 1 // only need to adjust one other 
    , d = c << 1 
    , e = d << 1 
}; 
+0

不幸的是,MS Visual Studio尚未实现C++ 14标准(二进制文字)。假设我要去移动操作符,即使我必须编辑整个枚举器,如果我删除或添加一个常量。 – neophoenix 2015-03-02 12:54:35

+0

@neophoenix我添加了一个方法,使长列表枚举更容易一些。 – Galik 2015-03-02 13:08:49

2

的一种方式,假设C++ 11,将

constexpr int func(int x) 
{ 
    return x << 1; 
} 

enum X 
{ 
    a = 1, 
    b = func(a), 
    c = func(b) 
}; 

func()可以被用来实现任何关系,你喜欢连续命名值之间。

C++ 11之前,备选方案可能包括

enum X 
{ 
    a = 1, 
    b = a << 1, 
    c = b << 1 
}; 

或(与宏)

#define func(x) x << 1 
enum X 
{ 
    a = 1, 
    b = func(a), 
    c = func(b) 
}; 
#undef func 
0

偷伟大idea of Rob,有指定如何递增的价值的方式枚举,这是不是很自动,但只要你的枚举总是相同的领域,你可以做这样的事情:

template <typename T, T(*INC)(const T), T start = {}> 
struct managed_enum 
{ 
    enum 
    { 
     a = start, 
     b = INC(a), 
     c = INC(b), 
    }; 
}; 

有了这个模板,你可以做到以下几点:

template<typename T> 
constexpr T shift_left(const T value) { return value << 1; } 

using shifted = managed_enum<int, shift_left<int>, 1>; 

你正在寻找(see here)枚举导致。那么,shifted不是一个枚举,而是一个结构,希望它没有关系。

定义不同的增值功能,您可以枚举不同的家庭自动增加,只要所有的人都只有managed_enumabc)三个值:

template<typename T> 
constexpr T shift_left(const T value) { return value << 1; } 

template<typename T> 
constexpr T increment(const T value) { return value + 1; } 

template<typename T> 
constexpr T bicrement(const T value) { return value + 2; } 

using shifted = managed_enum<int, shift_left<int>, 1>; 
using increment = managed_enum<int, increment<int>>; 
using bicrement = managed_enum<int, bicrement<int>>;