Delving into metaprogramming patterns, I discovered strange behavior with a range of enumerations in C ++. I get a warning: an integer overflow in an expression when it looks like I really don't want a value that goes beyond the enumeration. Here is the code:
#include <iostream>
#include <limits>
template <int i>
class pow {
public:
enum { result = 2*pow<i-1>::result};
};
template<>
class pow<0> {
public:
enum { result = 1};
};
enum test { one, max = 4294967295 };
enum test_2 { last = 4294967295*2 };
int main() {
std::cout << "pow<2>: \t" << pow<2>::result << std::endl;
std::cout << "pow<4>: \t" << pow<4>::result << std::endl;
std::cout << "pow<30>: \t" << pow<30>::result << std::endl;
std::cout << "pow<31>: \t" << pow<31>::result << std::endl;
std::cout << "max test: \t" <<
std::numeric_limits<std::underlying_type<test>::type>::max() << std::endl;
std::cout << "max test_2: \t" <<
std::numeric_limits<std::underlying_type<test_2>::type>::max() << std::endl;
return 0;
}
Compilation output:
test.cpp:7:19: warning: integer overflow in expression [-Woverflow]
enum { result = 2*pow<i-1>::result};
^
test.cpp:7:7: warning: overflow in constant expression [-fpermissive]
enum { result = 2*pow<i-1>::result};
Program output:
pow<2>: 4
pow<4>: 16
pow<30>: 1073741824
pow<31>: -2147483648
max test: 4294967295
max test_2: 18446744073709551615
Why does an enumeration in the pow class have a smaller range? As far as I understand, for each value of "i" I have an instance of another class, so it has a separate enumeration type. Therefore, for 'i'> 31, the enumeration must be 64 bits, for example test_2. Where am I mistaken?
I tried gcc 4.8 and gcc 5.4 and the results are the same.