Why doesn't the following minimal example compile with c++11 nor c++14, but compiles in c++17 and c++2a?
#include <iostream>
#include <limits>
#include <vector>
// works:
// static constexpr int VALUE_LIMIT_A = std::numeric_limits<int>::max();
class Classy {
// does not work in c++11 (constexpr introduced) nor c++14:
// works if c++17 or newer:
static constexpr int VALUE_LIMIT_A = std::numeric_limits<int>::max();
int VALUE_LIMIT_B = std::numeric_limits<int>::max();
public:
explicit Classy();
std::vector<int> classy;
};
Classy::Classy() {
// does not work:
classy.resize(3, VALUE_LIMIT_A);
// works:
// classy.resize(3, std::numeric_limits<int>::max());
// works:
// std::cout << VALUE_LIMIT_A;
// works:
// classy.resize(3, VALUE_LIMIT_B);
}
// required in c++11 and c++14
// constexpr int Classy::VALUE_LIMIT_A;
int main() {
Classy classy{};
for (const auto& elem : classy.classy) {
std::cout << elem << ",";
}
std::cout << "\n";
}
Here is output with c++11:
$ g++ -std=c++11 main.cpp && ./a.out
/tmp/ccon7pPo.o: In function `Classy::Classy()':
main.cpp:(.text+0x31): undefined reference to `Classy::VALUE_LIMIT_A'
collect2: error: ld returned 1 exit status
Here is output with c++17:
$ g++ -std=c++17 main.cpp && ./a.out
2147483647,2147483647,2147483647,
Because since C++17, the definition of the constexpr static data member at namespace scope is not required again.
If a const
non-inline (since C++17)static data memberor a constexpr static data member (since C++11)is odr-used, a definition at namespace scope is still required, but it cannot have an initializer.This definition is deprecated for constexpr data members (since C++17).struct X { static const int n = 1; static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used const int X::n; // … so a definition is necessary constexpr int X::m; // … (except for X::m in C++17)If a static data member is declared
constexpr, it is implicitlyinlineand does not need to be redeclared at namespace scope. This redeclaration without an initializer (formerly required as shown above) is still permitted, but is deprecated. (since C++17)
And note that std::vector::resize takes the 2nd parameter by reference; which cause VALUE_LIMIT_A to be odr-used for classy.resize(3, VALUE_LIMIT_A);.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With