为什么以下C++元编程代码在 N=100 时给出编译错误,但对于小 N 运行良好

Why does following C++ meta-programming code gives compilation error for N=100 but runs fine for small N?

本文关键字:错误 编译 运行 于小 C++ 编程 代码 为什么      更新时间:2023-10-16
#include<math.h>
#include<iostream>
using namespace std;
template <int x, int N> struct f{
        static const int res = x*(f<x, N-1>::res);
};
template <int x> struct f<x, 0>{
        static const int res = 1;
};
int main(){
        for(int i=0;i<1000000;++i)
                int a = (f<3, 100>::res);
}

如果我将 f<3, 100> 更改为 f<3, 10>代码运行正常。但是对于 100,它会给出以下错误:

.
.
.    
k.cpp:7:26:   recursively required from ‘const int f<3, 99>::res’
    k.cpp:7:26:   required from ‘const int f<3, 100>::res’
    k.cpp:16:23:   required from here
    k.cpp:7:19: error: initializer invalid for static member with constructor
    k.cpp:7:19: error: ‘f<3, 98>::res’ cannot be initialized by a non-constant expression when being declared
    k.cpp: In instantiation of ‘const int f<3, 99>::res’:
    k.cpp:7:26:   required from ‘const int f<3, 100>::res’
    k.cpp:16:23:   required from here
    k.cpp:7:19: error: initializer invalid for static member with constructor
    k.cpp:7:19: error: ‘f<3, 99>::res’ cannot be initialized by a non-constant expression when being declared
    k.cpp: In instantiation of ‘const int f<3, 100>::res’:
    k.cpp:16:23:   required from here
    k.cpp:7:19: error: initializer invalid for static member with constructor
    k.cpp:7:19: error: ‘f<3, 100>::res’ cannot be initialized by a non-constant expression when being declared

我是元编程的新手。虽然错误看起来像与const有关的东西,但事实并非如此。有人可以帮我理解吗?

启用警告并仔细阅读错误输出:

warning: integer overflow in expression [-Woverflow]
         static const int res = x*(f<x, N-1>::res);
                                ~^~~~~~~~~~~~~~~~~
error: overflow in constant expression [-fpermissive]
         static const int res = x*(f<x, N-1>::res);
                          ^~~

对于足够大的N值,您将有一个有符号整数溢出,这是运行时上下文中的未定义行为,并在常量表达式中产生编译时错误

如果我尝试int a = (f<3, 20>::res);我会得到

warning C4307: '*': integral constant overflow

int作为long long可以克服这一点,并为f<3, 20>提供3486784401。

这可以应对高达f<3, 39> 4052555153018976267然后溢出。

道德:警告是有帮助的。