I have the following piece of code, that behaves as expected on gcc and clang. However, MSVC gives me an unexpected result.
Lets first look at the problematic code.
#include <iostream>
// -----------------------------------------------
class Test // Dummy for MCVE
{
public:
Test();
void Print();
private:
int arr[5];
};
Test tst;
// -----------------------------------------------
template<typename T>
struct range // some stuff not needed by example removed
{
constexpr range(T n) : b(0), e(n) {}
constexpr range(T b, T e) : b(b), e(e) {}
struct iterator
{
T operator*() { return i; }
iterator& operator++() { ++i; return *this; }
bool operator!=(iterator other) { return i != other.i ; }
T i;
};
iterator begin() const { return{ b }; }
iterator end() const { return{ e }; }
private:
T b,e;
};
constexpr range<int> coord(5);
// -----------------------------------------------
Test::Test()
{
for(auto i : coord)
arr[i]=i;
}
void Test::Print()
{
for(auto i : coord)
std::cout << arr[i] << std::endl;
}
// -----------------------------------------------
int main()
{
tst.Print();
}
Now, on both clang and gcc this prints '0 1 2 3 4'
However, on MSVC this prints '0 0 0 0 0'
The reason being that when the constructor on the global variable tst
runs, 'coord' have yet not been initialized (to 0,5), but it is also not random, but rather (0,0).
To me it would make sense that constexpr
initialization happens before regular initialization. Is MSVC conformant in this behaviour?
I should perhaps note that I'm using MSVC version 14.0.22823.1, and that the expected result can be obtained by changing the order of the declarations