I was trying to create a unit test framework for myself, and it worked fine until I made it into a static lib. The static container unit_base::_units is used before its construction.
I reproduced the issue with the following simpler version:
lib.lib
lib.h
#pragma once
#include <vector>
namespace est {
class unit_base
{
public:
unit_base();
class unit_vec : public std::vector<unit_base*> {
public:
unit_vec();
~unit_vec();
};
static unit_vec& get_units();
virtual bool run() const = 0;
private:
static unit_vec _units;
};
bool test_all();
}
lib.c
#include "lib.h"
#include <iostream>
namespace est {
unit_base::unit_vec unit_base::_units;
unit_base::unit_base() {
_units.push_back(this);
std::cout << "push unit to: " << &_units << std::endl;
}
unit_base::unit_vec::unit_vec() {
std::cout << "vec(): " << this << std::endl;
}
unit_base::unit_vec::~unit_vec() {
std::cout << "~vec(): " << this << std::endl;
}
unit_base::unit_vec& unit_base::get_units()
{
return _units;
}
bool test_all()
{
std::cout << "before get_units" << std::endl;
auto& units = unit_base::get_units();
std::cout << "after get units" << std::endl;
for(auto& u: units) {
u->run();
}
return false;
}
}
exe
test.cpp
#include "lib.h"
#include <iostream>
namespace est
{
bool est_test_func();
class est_test : public unit_base
{
public:
est_test():
unit_base() {}
bool run() const override
{
return est_test_func();
}
};
static est_test est_test_inst;
bool est_test_func() {
std::cout << "test" << std::endl;
return true;
}
}
int main(int argc, char** argv)
{
est::test_all();
}
The exe prints:
push unit to: 0x7f72dc873170
vec(): 0x7f72dc873170
before get_units
after get units
~vec(): 0x7f72dc873170
I tested it on Windows and WSL, both resulted in an empty _units for test_all(). I must be doing something terribly wrong, so I am here for help.
I created a repo with CMakeLists: https://github.com/Lucipetus/problemic.git