C++ C++;11初始化列表、数组和枚举的乐趣 背景

C++ C++;11初始化列表、数组和枚举的乐趣 背景,c++,initialization,c++11,C++,Initialization,C++11,C++11初始值设定项列表可用于初始化向量和数组,并将参数传递给构造函数 我在下面有一段代码,我想用eCOLORS从eCOLORS::First到eCOLORS::Last使用初始值设定项列表初始化这样一个数组。 原始代码 由于所有信息在编译时都是已知的,所以我认为有一种方法可以解决这个问题 enum class eCOLORS { kBLUE=0, kGREEN, kRED, kPURPLE, First=kBLUE, Last=kPURPLE }; templa

C++11初始值设定项列表可用于初始化向量和数组,并将参数传递给构造函数

我在下面有一段代码,我想用
eCOLORS
eCOLORS::First
eCOLORS::Last
使用初始值设定项列表初始化这样一个数组。

原始代码 由于所有信息在编译时都是已知的,所以我认为有一种方法可以解决这个问题

enum class eCOLORS 
{
    kBLUE=0, kGREEN, kRED, kPURPLE,
        First=kBLUE, Last=kPURPLE 
};

template< typename E >
size_t Size()
{
    return (size_t)(E::Last) - (size_t)(E::First) + 1;
}

struct Foo
{
    Foo( eCOLORS color ) { }
};

int main(int argc, char** argv)
{
    Foo a[2] = {
        { eCOLORS::kRED   },
        { eCOLORS::kGREEN }
    };  // works, but requires manual maintenance if I add another color

    /* how to feed v with all the enums from First to Last
       without hard-coding?
    Foo v[Size<eCOLORS>()] = {

    };
    */
}

没有一种使用初始值设定项列表的自动方法可以做到这一点,但是如果您知道枚举的第一个和最后一个值,您可以通过使用
for
循环来插入值,通过算法来做到这一点。

我认为使用初始值设定项列表无法做到这一点。这不是他们想要的东西。我认为您可以通过定义一个迭代器来管理一个不错的解决方案,该迭代器将迭代任何具有
First
Last
成员的枚举

但首先,您对
大小的定义不太正确

template< typename E >
constexpr size_t Size()
{
    return (size_t)(E::Last) - (size_t)(E::First) + 1;
}
模板
constexpr size\u t size()
{
返回(大小)(E::Last)-(大小)(E::First)+1;
}
声明它
constexpr
意味着它的定义是编译时常量。因此,您可以在模板参数等中使用它


我现在没有时间为您创建range类。枚举值和整数对于枚举类是不可互换的,这有点复杂。但这并不难。您可以使用此问题“”作为起点。基本上使用向量初始化器,它从[begin,end]对与range类(如该问题中所讨论的)结合进行初始化。

您可以使用可变模板和我将称之为“索引技巧”的方法来完成此操作

typedef std::底层类型::底层类型;
//只是一种携带可变数字包的类型
模板结构索引{};
//用于从第一个开始构建计数包的模板
//第三个参数是累加器
模板
构造索引;
//基本情况
模板
struct使_指数成为宏观解决方案

#include <stdio.h>
#include <initializer_list>

#define COLORS(V,E) \
    V(RED) \
    V(GREEN) \
    E(BLUE)

#define COMMA(V) \
    V,

#define NCOMMA(V) \
    V

#define SCOMMA(V) \
    #V,

#define SNCOMMA(E) \
    #E

enum Colors {
    COLORS(COMMA,NCOMMA)
};

const char * colors[] = {
    COLORS(SCOMMA,SNCOMMA)
};

#define INIT_LIST(V) \
    { V(COMMA,NCOMMA) }

int main(int argc, char  **argv) {
    for ( auto i : INIT_LIST(COLORS) ) {
        printf("%s\n", colors[i]);
    }
}
#包括
#包括
#定义颜色(V、E)\
V(红色)\
V(绿色)\
E(蓝色)
#定义逗号(V)\
v
#定义NCOMMA(五)\
v
#定义SCOMMA(五)\
#五,,
#定义逗号(E)\
#E
枚举颜色{
颜色(逗号、NCOMMA)
};
常量字符*颜色[]={
颜色(SCOMMA、SNCOMMA)
};
#定义初始列表(V)\
{V(逗号,NCOMMA)}
int main(int argc,字符**argv){
用于(自动i:INIT_列表(颜色)){
printf(“%s\n”,颜色[i]);
}
}

我喜欢你的问题。很久以前,这种事情通常是用X宏来处理的

我是一名c++11新手,但经过一番努力,我得到了某种解决方案(g++4.8.4):

我保留了your Size(),但添加了一些其他样板文件,以使初始化更容易阅读

template< typename E > constexpr size_t Size() { return (size_t)(E::Last) - (size_t)(E::First) + 1; }
template< typename E > constexpr size_t as_sizet( E s ) { return (size_t)s; }
template< typename E > constexpr E operator++( E& s, int ) { return (E)(1 + (size_t)s); }
template< typename E > constexpr bool operator<=( E& a, E& b ) { return (size_t)a < (size_t)b; }
templateconstexpr size_t size(){return(size_t)(E::Last)-(size_t)(E::First)+1;}
模板constexpr size\u t as_sizet(es){return(size\u t)s;}
模板constexpr E操作符++(E&s,int){return(E)(1+(size_t)s)}
模板constexpr布尔运算符
constexpr arr和init_数组(arr和zArr,E sym=E::First,E junk=E::Last)
{
返回sym constexpr E next(E&s){return(E)(1+(size_t)s);}
模板
constexpr-EARR和init_数组(EARR和zArr,E-sym=E::First)
{

return sym我想知道是否有一个宏解决方案,那么?当然,函数模板更可取……但是,您的算法假设第一个和最后一个之间的所有值都有一个枚举。@John:是的,尽管问题的粗体部分暗示了这一点。这就是为什么我们需要更强大的静态反射。
max_枚举器
是_枚举器
下一个_枚举器
。类型特征做了很多,但我们可以使用更多。C++11初始值设定项列表不能用于初始化数组——虽然语法看起来类似,但数组实际上使用聚合初始化。
#include <stdio.h>
#include <initializer_list>

#define COLORS(V,E) \
    V(RED) \
    V(GREEN) \
    E(BLUE)

#define COMMA(V) \
    V,

#define NCOMMA(V) \
    V

#define SCOMMA(V) \
    #V,

#define SNCOMMA(E) \
    #E

enum Colors {
    COLORS(COMMA,NCOMMA)
};

const char * colors[] = {
    COLORS(SCOMMA,SNCOMMA)
};

#define INIT_LIST(V) \
    { V(COMMA,NCOMMA) }

int main(int argc, char  **argv) {
    for ( auto i : INIT_LIST(COLORS) ) {
        printf("%s\n", colors[i]);
    }
}
enum class Symbols { FOO, BAR, BAZ, First=FOO, Last=BAZ };
template< typename E > constexpr size_t Size() { return (size_t)(E::Last) - (size_t)(E::First) + 1; }
template< typename E > constexpr size_t as_sizet( E s ) { return (size_t)s; }
template< typename E > constexpr E operator++( E& s, int ) { return (E)(1 + (size_t)s); }
template< typename E > constexpr bool operator<=( E& a, E& b ) { return (size_t)a < (size_t)b; }
template< typename E, typename EARR > 
constexpr EARR& init_array( EARR& zArr, E sym = E::First, E junk = E::Last )
{
    return sym <= E::Last ? init_array( zArr, sym++, zArr[ as_sizet( sym ) ] = sym ) : zArr;
}
typedef Symbols SymbolArr[ Size<Symbols>() ];
static SymbolArr symbolArr;
SymbolArr& symbolArrRef = init_array<Symbols, SymbolArr>(symbolArr);
template< typename E > constexpr E next( E& s ) { return (E)(1 + (size_t)s); }

template< typename E, typename EARR > 
constexpr EARR& init_array( EARR& zArr, E sym = E::First )
{
    return sym <= E::Last ? init_array( zArr, next( zArr[ as_sizet( sym ) ] = sym ) ) : zArr;
}