Why does the ASSERT_EQ
below cause an undefined reference to Bar::kBar
error?
To compile: g++ a.cc -lgtest -lpthread
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
From the Googletest FAQ:
If your class has a static data member:
// foo.h
class Foo {
...
static const int kBar = 100;
};
You also need to define it outside of the class body in foo.cc:
const int Foo::kBar; // No initializer here.
Otherwise your code is invalid C++, and may break in unexpected ways. In particular, using it in Google Test comparison assertions (EXPECT_EQ, etc) will generate an "undefined reference" linker error.
This explanation is rather enigmatic. (Why is it "invalid C++?") That is probably because a satisfactory explanation is rather technical.
Even though your class bar
declares the static data member kBar
with
an initializer, that does not suffice to provide the data member with a
definition that has external linkage (i.e. that the linker can see), and
without one any code that attempts to odr-use1Bar::kBar
will
encounter an undefined reference linkage error. This can be illustrated
without involving Googletest:
foobar.cpp
#include <cstdlib>
class Bar {
public:
static const std::size_t kBar = 0;
};
bool foo(std::size_t const & k)
{
return k == 0;
}
int main()
{
return foo(Bar::kBar);
}
Try to build:
$ g++ foobar.cpp
/tmp/ccWaEsDu.o: In function `main':
foobar.cpp:(.text+0x1c): undefined reference to `Bar::kBar'
collect2: error: ld returned 1 exit status
The solution is as per the FAQ:
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
const size_t Bar::kBar;
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
As of C++17 you will be able to omit the out-of-class definition if
you prefix the initialized in-class declaration with inline
(which
will make it a definition).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With