C++ C++;11初始化列表、数组和枚举的乐趣 背景
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
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;
}