I defined a constructor of a class as below:
struct TestClass
{
TestClass(std::uint8_t, std::vector<Type>)
{
//...
}
};
Then I want to use google test to do a unit test, the compile error occurs when I try to construct an instance of TestClass, as below:
TEST(name1,name2)
{
//...
Type element;
std::vector<Type> lst{element};
TestClass instance(0, lst);
//...
}
The gnu compiler reports:
"In function
name1_name2_Test::TestBody()':test.cpp:(.text+0x165d): undefined reference to
TestClass::TestClass(signed char, std::vector< Type, std::allocator< Type>)' collect2: error: ld returned 1 exit status"
Below is my evironment:
g++ version: 5.3.0
google test version: 1.7.0
the compile command: g++ -D_GLIBCXX_USE_CXX11_ABI=0 test.cpp -std=c++14 -lboost_system -lgtest -lgtest_main -lpthread
Have you ever met similar problem? Please give me some suggestions, thanks.
Below code can cause above error:
#include <gtest/gtest.h>
struct Element
{
Element(const std::vector<std::uint8_t>& element) : element_(element){}
std::vector<std::uint8_t> element_;
};
using ElementList = std::vector<Element>;
struct Information
{
Information(std::uint8_t, ElementList) {}
std::int8_t number_;
ElementList eleLst_;
};
TEST(name1,name2)
{
std::uint8_t number = 0;
std::vector<std::uint8_t> vec{1,2,3,4};
Element elem(vec);
ElementList lst{elem};
Information info(std::int8_t(0), lst); //false
}
GTEST_API_ int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Below is compile message:
/tmp/ccUzsTfz.o: In function
name1_name2_Test::TestBody()': test.cpp:(.text+0x130): undefined reference to
Information::Information(unsigned char, std::vector< Element, std::allocator< Element > >)'
collect2: error: ld returned 1 exit status
Your signature is:
struct TestClass
{
TestClass(std::uint8_t, std::vector<Type>)
{
//...
}
};
And the LINKER looks for:
TestClass::TestClass(signed char, std::vector< Type>, std::allocator< Type>);
Your TestClass' constructor definition does not contain an allocator-parameter!
That's why there's no function instantiated containing the allocator-parameter and consequently it is not found by the linker.
http://www.cplusplus.com/doc/tutorial/classes/ // Basics
https://isocpp.org/wiki/faq/ctors // Good to know
TestClass(signed char, std::vector<Type>)
as the constructor is enough, if you use a standard allocator of type "Type"..
See: http://de.cppreference.com/w/cpp/container/vector
THis is the signature of the class:
template<
class T,
class Allocator = std::allocator<T>
> class vector;
As you can see, it has a default template parameter assignment for Allocator, which is std::allocator.
This way, you only have to specify an allocator In the template parameter list, if you have a custom allocator, i.e.:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
struct Type {};
template <typename T>
class MyBatchAllocator {
};
template <typename TAllocator = std::allocator<Type>>
class TestClass {
public:
TestClass(signed char, const std::vector<Type, TAllocator>&) {
// ...
}
};
int main()
{
// main.cpp
Type element;
std::vector<Type, MyBatchAllocator<Type>> lst({ element });
TestClass<MyBatchAllocator<Type>> tc(0, lst);
}
Otherwise, if you use standard allocators use this:
int main() {
Type element;
std::vector<Type> lst2({ element });
TestClass<> tc2(0, lst2);
// Yes, if TestClass is a template with a single
// defaulted template parameter the empty <> are required.
}
If you want to make your life with those templates easier, you could employ an alias:
using DefaultTestClass = TestClass<>;
and call it like:
DefaultTestClass tc3(0, lst2);