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

标签 c++ initialization c++11

背景

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

下面有一段代码,我想用 eCOLORSeCOLORS::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>()] = {

    };
    */
}

丑陋的伪答案

共识似乎是目前没有办法做到这一点。

My original intent in asking this question is, I want to automagically create an array of Foo objects whose initialization is solely based on the enumeration of eColors. I wanted a no maintenance solution that would work even after you add more entries into eColors.

使用 this earlier post 中的 Enum 类,我可以编写一个函数模板来提供我需要的功能。即使不使用该 Enum 类,您仍然可以从 eCOLORS::First 循环到 eCOLORS::Last,以及一些丑陋的转换。

我丑陋的伪答案很笨拙(没有编译时初始化列表好),但至少它是零维护。

注意:如果出现更好的解决方案,我会相应地更新 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>();
}

最佳答案

您可以使用可变参数模板以及我将称之为“索引技巧”的方法来做到这一点。

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());
}

这假设所有枚举器都是连续的,并且需要 GCC 4.6 不支持的 std::underlying_type(将在 4.7 中,但您可以 emulate it to a certain extent )。

关于C++11 初始化列表、数组和枚举的乐趣,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8606315/

相关文章:

c++ - 在 std::map 中,如何编写分配器来接受键作为值的构造函数参数?

c++ - 对 std::vector 使用 std::copy_if 时出现断言错误

c++ - 在使用 Nifty Counter C++ Idiom 时,构造函数必须被调用两次吗?

c++ - 如何检查类是否在 C++14 中有指针

c++ - 如何从缓冲区及其大小填充std::vector?

c++ - 模板化赋值运算符模板实例化失败

c++ - main.cpp|15|错误 : invalid conversion from 'const char*' to 'char' [-fpermissive]| error when making a game

c++ - 使用 C++ 编写的应用程序的 64 个连接限制 **帮助**

swift - 如何满足包含初始值设定项的协议(protocol)?

c++ - 警告 : variable is uninitialized