Since C++17, I've been experimenting easier ways to get class static variables. I'm writing a header-only library. Apparently the new meaning of inline
for variables is suited for this.
class thingy {
static inline reporter rep;
};
But I've been getting runtime errors.
I'm using Visual Studio 15.6.4
To test, the following:
thingy
has a static member variablefoo.h
#pragma once
#include <iostream>
using namespace std;
struct reporter {
reporter() {
cout << "reporter() - " << this << endl;
}
~reporter() {
cout << "~reporter() - " << this << endl;
}
};
class thingy {
static inline reporter rep;
};
main.cpp
#include "foo.h"
int main() {}
foo.cpp
#include "foo.h"
Most disappointingly, it prints:
reporter() - 00007FF670E47C80
reporter() - 00007FF670E47C80
~reporter() - 00007FF670E47C80
~reporter() - 00007FF670E47C80
As you can see, it is constructed twice and destructed twice at the same location - not good.
Am I misunderstanding what inline
on variables is for?
Is there another way to get class statics in header only? Has this changed in C++17?
It looks like a bug in VS2017.
A few relevant bug reports can be found, although they do not exactly meet your case:
This will be addressed in 15.7 - thanks for the report! Combining multiple guards for adjacent static variables into a single guard is a backend optimization which can go wrong when inlining under certain circumstances. That's basically the issue here.
Hopefully this static variable when inline-ed bug will be fixed soon in their next patch.
Meanwhile, I found that compiling in Release Mode
makes your reporter
initialized only once as expected, while in Debug Mode
this bug occurs for their backend optimization.
So I guess this won't be going into your products, at least.