I am trying to pass an initializer list to the constructor of a struct, whose parameter is std::vector
, but I am getting unexpected results in Visual Studio Community. Here is the code to reproduce the problem:
#include <vector>
#include <iostream>
using namespace std;
struct ST
{
std::size_t size1;
std::size_t size2;
constexpr ST(std::vector<int> production) : size1(production.size())
{
size2 = production.size();
}
};
static constexpr auto get_ST()
{
return ST({ 1, 2, 3 });
}
int main()
{
auto par = get_ST();
std::cout << par.size1 << " " << par.size2 << std::endl;
constexpr auto par2 = get_ST();
std::cout << par2.size1 << " " << par2.size2 << std::endl;
}
On Visual Studio Community, the output is:
3 3
3 0
while in gcc
, I am getting the following output (https://godbolt.org/z/reqqdcEEh):
3 3
3 3
From the output, it is clear that MSVC is not calling the body of constructor when the result is evaluated in constexpr context. Does anyone know if this is Standard C++ compliant or the bug in MSVC?
Yes, this is a bug in MSVC - interestingly, it is a regression; this worked under MSVC 19.28 (VS 16.9), the first version to support constexpr destructor, but not in later versions.
A reduced version is:
struct V {
int z = 1;
constexpr ~V() { z = 2; }
};
struct S {
int i, j;
constexpr S(V v) : i(v.z) {
j = v.z;
}
};
int main() {
constexpr S s{V{}};
return s.i * 10 + s.j;
}
A workaround is to take the constructor argument by const reference or by rvalue reference (or both); hopefully this will work for you.
I've reported this to Microsoft at https://developercommunity.visualstudio.com/t/Premature-constexpr-destruction-of-by-va/10547472 so you can track the issue there.