C++ 11使用初始化列表,数组和枚举的乐趣

kfm*_*e04 5 c++ initialization c++11

背景

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

我有以下情况我想去来初始化所有的枚举这种阵列的一段代码eCOLORSeCOLORS::FirsteCOLORS::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>()] = {

    };
    */
}
Run Code Online (Sandbox Code Playgroud)

丑陋的伪答案

目前的共识似乎是目前没有办法解决这个问题.

我最初提出这个问题的意图是,我想自动创建一个Foo对象数组,其初始化完全基于枚举eColors.我想要一个无需维护的解决方案,即使你添加了更多的条目,它也能工作eColors.

使用上一篇文章中的Enum类,我可以编写一个函数模板,为我提供所需的功能.即使不使用枚举类,你仍然可以从循环eCOLORS::FirsteCOLORS::Last,有一些丑陋蒙上一起.

我丑陋的伪答案是kludgy(没有编译时初始化列表那么好),但至少它是零维护.

注意:如果出现更好的解决方案,我将相应地更新OP.

template <typename T, typename E>
std::vector< T >
Initialize_With_Enums()
{
  std::vector< T > v;
  for( auto p : Enum<E>() )
    v.push_back( T( p ));
  return v;
}

int main( int argc, char** argv )
{
  auto w = Initialize_With_Enum<Foo,eCOLORS>();
}
Run Code Online (Sandbox Code Playgroud)

R. *_*des 7

您可以使用可变参数模板以及我将称之为"索引技巧"的方法来完成此操作.

typedef std::underlying_type<eCOLORS>::type underlying;

// just a type to carry around variadic pack of numbers
template <underlying...> struct indices {};

// A template to build up a pack of Count numbers from first
// third parameter is an accumulator
template <underlying First, underlying Count, typename Acc = indices<>>
struct make_indices;

// base case
template <underlying X, underlying... Acc>
struct make_indices<X, 0, indices<Acc...>> { typedef indices<Acc...> type; };
// recursive build up of the pack
template <underlying First, underlying Count, underlying... Acc>
struct make_indices<First, Count, indices<Acc...>>
    : make_indices<First, Count-1, indices<First+Count-1, Acc...>> {};

size_t const max_colors = underlying(eCOLORS::Last) - underlying(eCOLORS::First)+1;

// shortcut
typedef make_indices<
          underlying(eCOLORS::First),
          max_colors
        >::type all_eCOLORS_indices;

// takes a dummy parameter with the pack we built
template <underlying... Indices>
std::array<eCOLORS, max_colors> const& all_colors(indices<Indices...>) {
    // convert each number to the enum and stick it in an static array
    static std::array<eCOLORS, max_colors> const all = {
        eCOLORS(Indices)...
    };
    return all;
}

std::array<eCOLORS, max_colors> const& all_colors() {
    // create a dummy object of the indices pack type and pass it
    return all_colors(all_eCOLORS_indices());
}
Run Code Online (Sandbox Code Playgroud)

这假设所有枚举器都是顺序的,并且std::underlying_typeGCC 4.6中不支持的需求(将在4.7中,但您可以在一定程度上模拟它).

  • 这就是我们需要更强大的静态反射的原因.`max_enumator <>`,`is_enumator <>`,`next_enumator <>`.类型特征做了很多,但我们可以使用更多. (2认同)

Pet*_*der 0

没有使用初始值设定项列表自动执行此操作的方法,但如果您通过仅使用循环for插入值来知道枚举的第一个和最后一个值,则可以通过算法来执行此操作。