I have a simple setup. My base class is:
class PartBase {
private:
std::string_view m_Name;
public:
explicit PartBase(std::string_view name)
: m_Name(name){};
std::string_view getName() { return m_Name; };
void build() {
std::cout << "Started building " << getName() << "\n";
buildPart();
std::cout << "Building " << getName() << " completed.\n";
}
virtual void buildPart(){};
};
Then I have two classes one level higher:
class Rib : public PartBase {
public:
explicit Rib(const std::string& partName)
: PartBase(partName){};
void buildPart() override {
std::cout << "Started building " << getName() << "\n";
};
};
and
class Wing : public PartBase {
private:
std::vector<Rib> m_Ribs;
public:
explicit Wing(const std::string& partName, spdlog::logger& logger)
: PartBase(partName, logger){};
void buildPart() override {
std::cout << "Started building " << getName() << "\n";
};
};
Then I have a dumb catch2 test that simply creates a class.
TEST_CASE("WingPartTests", "[tests_wing]") {
SECTION("test_wing_creation ") {
// Check creation.
REQUIRE_NOTHROW(Wing("abc"));
// Get wing name.
auto wing = Wing("abc");
REQUIRE(wing.getName() == "abc");
}
}
The problem is that this test passes on Linux with gcc (c++20) no problem. It also builds on msvc, but the tests don't pass. The test fails with the following output:
7: ..... test\parts\test_wing.cpp(21): FAILED:
7: REQUIRE( wing.getName() == "abc" )
7: with expansion:
7: "
7: bc" == "abc"
This I guess makes the test not so "dumb" after all, but I have to admit I have no idea what the problem is. I work on linux, so the only output I get is from the CI. Would anybody know?
You are creating std::string_view
with a temporary object that is destroyed when the constructor finishes. It is equivalent to this:
int main() {
auto wing = std::string_view(std::string("abc"));
// Prints "bc" on Visual Studio
std::cout << wing << std::endl;
}
This does not work, as string_view
is a simple pointer that does not extend the lifetime of the data:
A typical implementation holds only two members: a pointer to constant CharT and a size.
Change the type of m_Name
to std::string
to copy the data.