C++ c++;带有大开关的致命错误C1061,元编程

C++ c++;带有大开关的致命错误C1061,元编程,c++,visual-studio-2008,metaprogramming,compiler-errors,switch-statement,C++,Visual Studio 2008,Metaprogramming,Compiler Errors,Switch Statement,这就是代码: static inline void shrinkData(const vector<Data> &data, unsigned short shrinkType){ #define CASE_N(N) \ case(N): \ ptr = MemoryManager::requestMemory(n*sizeof(ShrinkData<N>)); \ for(int i=0; i<n; i++

这就是代码:

static inline void 
shrinkData(const vector<Data> &data, unsigned short shrinkType){
    #define CASE_N(N) \
    case(N): \
        ptr = MemoryManager::requestMemory(n*sizeof(ShrinkData<N>)); \
        for(int i=0; i<n; i++){ \
            new(ptr) ShrinkData<N>(data[i]); \
            ptr+=sizeof(ShrinkData<N>); \
        } \
        return;


    int n = data.size();
    char* ptr;

    switch(shrinkType){
    case(0):
        return;
    CASE_N(1)
    CASE_N(2)
    CASE_N(3)
    ....
    CASE_N(255)
}
静态内联void
收缩数据(常量向量和数据,无符号短收缩类型){
#定义案例N(N)\
案例(N):\
ptr=MemoryManager::requestMemory(n*sizeof(ShrinkData))\

对于(inti=0;i只是推测,但是函数是内联标记的,并且它也使用模板,这可能是额外嵌套的部分来源


然而,在我看来,更可能的情况是,您所达到的资源限制实际上可能没有“嵌套级别”那么明确但是,这是被认为是命中它的最常见原因,所以这就是错误消息所指的。

我认为错误消息是假的。可能确实存在编译器限制,但不太可能是块嵌套

无论如何,如果您将每个
案例的代码放入其自己的函数模板中并调用它,会发生什么情况?
此外,内联此函数很可能不会为您带来任何好处,因为它将请求内存并执行循环。相比之下,函数调用开销必须可以忽略。(无论循环所需的迭代次数有多少,单独设置它的成本可能是调用函数的一半。)
最后,为了以防万一,我会尝试去掉宏

代码可能如下所示:

// Beware, brain-compiled code ahead!
template<unsigned short N>
void do_it(int n)
{
  char* ptr = MemoryManager::requestMemory(n*sizeof(ShrinkData<N>));
  for(int i=0; i<n; i++){
    new(ptr) ShrinkData<N>(data[i]);
    ptr+=sizeof(ShrinkData<N>);
  }
}

static void 
shrinkData(const vector<Data> &data, unsigned short shrinkType)
{
  const std::vector<Data>::size_type n = data.size();
  switch(shrinkType){
    case   0: break
    case   1: do_it<  1>(n); break;
    case   2: do_it<  2>(n); break;
    .
    .
    .
    case 254: do_it<254>(n); break;
    case 255: do_it<255>(n); break;
}
//当心,brain提前编译了代码!
模板
void do_it(int n)
{
char*ptr=MemoryManager::requestMemory(n*sizeof(ShrinkData));
对于(int i=0;i(n);中断;
案例2:do_it<2>(n);中断;
.
.
.
案例254:do_it(n);中断;
案例255:do_it(n);中断;
}
根据这一点,编译器中有一个“功能”,只允许有限数量的循环。我从未遇到过这种情况。请尝试将ptr初始化和以下for循环放在一个块中。另一个解决方案是创建覆盖整个代码段的模板函数,这样宏就会变成这样:

#define CASE_N(N) \
case(N): \
    ptr = requestAndInitialize<N>(data); \
    return;
#定义案例N(N)\
案例(N):\
ptr=请求和初始化(数据)\
返回;

我只是在一些自动生成的代码中遇到了这个问题;用于循环而不是开关,但问题相同。 我没有把所有的循环放在它们自己的块中——这会让代码在过程中变得更难看——我显然通过将迭代器的声明移到循环之外,C风格解决了这个问题

我怀疑,如果我们添加太多的循环,问题可能会再次出现,因为我相信这是因为存储范围数据的空间不足,但同时这会更好

编辑:果然,这个问题在1.5年后再次出现。添加额外的嵌套级别修复了它。
我想这个答案更符合我自己的利益,而不是其他人的利益。

您可能需要说明编译器的确切版本。对不起,我怎么知道?我正在使用Visual Studio 2008Professional@SilverSun-我添加了构造函数。看起来很大,但实际上做的不多-只是初始化数据成员。构造函数在不要这个开关function@sbi关于内联,是的,也许你是对的-但是内存是预先分配的,循环只迭代4-64项..这可能与你的问题无关,但是复制构造函数看起来很可疑。为什么你需要复制构造,而不是赋值和析构函数?从我所看到的,美国作为数据成员,
IDataMember
的ge两者都不需要。嘿,这确实起到了作用!将“case(N):”后面的所有内容放入一个块中,使它可以编译!有人知道有什么区别吗?我想编译器跟踪连续循环是为了某种目的(可能是为了优化).单独块中的循环不是连续的。不在同一范围内。@Mat:如果将鼠标悬停在“向上投票”按钮上,您将看到一条消息,上面写着“此答案很有用”.这正是这个按钮的作用:当你认为答案有用时点击它。我不知道有人会如何庆祝一个好的答案而不去投票…@sbi:公平地说,他确实接受了这个最佳答案。不过,我不会再抱怨10分了。我不能点击它,我没有帐户。但我很感激你的回答(尽管如此:)
// Beware, brain-compiled code ahead!
template<unsigned short N>
void do_it(int n)
{
  char* ptr = MemoryManager::requestMemory(n*sizeof(ShrinkData<N>));
  for(int i=0; i<n; i++){
    new(ptr) ShrinkData<N>(data[i]);
    ptr+=sizeof(ShrinkData<N>);
  }
}

static void 
shrinkData(const vector<Data> &data, unsigned short shrinkType)
{
  const std::vector<Data>::size_type n = data.size();
  switch(shrinkType){
    case   0: break
    case   1: do_it<  1>(n); break;
    case   2: do_it<  2>(n); break;
    .
    .
    .
    case 254: do_it<254>(n); break;
    case 255: do_it<255>(n); break;
}
#define CASE_N(N) \
case(N): \
    ptr = requestAndInitialize<N>(data); \
    return;