【问题标题】:How to solve an unexpect std::allocator when compile code?编译代码时如何解决意外的 std::allocator?
【发布时间】:2017-04-06 02:34:31
【问题描述】:

我定义了一个类的构造函数如下:

struct TestClass
{
    TestClass(std::uint8_t, std::vector<Type>)
    {
        //...
    }
};

那我想用google test做一个单元测试,在我尝试构造TestClass的实例时出现编译错误,如下:

TEST(name1,name2)
{
    //...
    Type element;
    std::vector<Type> lst{element};
    TestClass instance(0, lst);
    //...
}

gnu 编译器报告:

"在函数name1_name2_Test::TestBody()':test.cpp:(.text+0x165d): undefined reference toTestClass::TestClass(signed char, std::vector)' collect2:错误:ld 返回 1 个退出状态”

下面是我的环境:

g++ 版本:5.3.0
谷歌测试版本:1.7.0
编译命令:g++ -D_GLIBCXX_USE_CXX11_ABI=0 test.cpp -std=c++14 -lboost_system -lgtest -lgtest_main -lpthread

你遇到过类似的问题吗?请给我一些建议,谢谢。

以下代码可能导致上述错误:

#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();
}

下面是编译信息:

/tmp/ccUzsTfz.o: 在函数name1_name2_Test::TestBody()': test.cpp:(.text+0x130): undefined reference toInformation::Information(unsigned char, std::vector>)'
collect2:错误:ld 返回 1 个退出状态

【问题讨论】:

  • 对不起,因为保密协议,我不能给你看完整的代码。在我看来,上面的错误信息足以描述我的情况,你应该有能力理解这个问题。 (以上代码是我原代码的抽象模型)
  • @ChenDong 不是完整的代码,而是仍然显示相同错误的 minimal 代码。
  • 不,这还不够。首先,它甚至不是完整的构建消息,但我猜它是在链接阶段出现的。这意味着错误可能在 TestClass 的定义中,或者可能在您使用它的方式中。您确定 uint8_t 和 signed char 在您的系统上是同一类型(而不仅仅是具有相同的表示形式)吗?
  • @stackoverflow.com/users/3545273/serge-ballesta 是的,我更新了一个最小的代码。请帮我解决这个问题,

标签: c++ googletest allocator


【解决方案1】:

您的签名是:

struct TestClass
{
    TestClass(std::uint8_t, std::vector<Type>)
    {
        //...
    }
};

然后 LINKER 寻找:

TestClass::TestClass(signed char, std::vector< Type>, std::allocator< Type>);

您的 TestClass 的构造函数定义不包含分配器参数!

这就是为什么没有实例化包含分配器参数的函数,因此链接器找不到它。

编辑:更多参考

http://www.cplusplus.com/doc/tutorial/classes/ // 基础

https://isocpp.org/wiki/faq/ctors // 很高兴知道

编辑:有一些误解

TestClass(signed char, std::vector<Type>)

构造函数就足够了,如果你使用“Type”类型的标准分配器..

见: http://de.cppreference.com/w/cpp/container/vector

这是类的签名:

template<
    class T,
    class Allocator = std::allocator<T>
> class vector;

如你所见,它对Allocator有一个默认的模板参数赋值,即std::allocator。

这样,你只需要在模板参数列表中指定一个分配器,如果你有自定义分配器,即:

#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);
}

否则,如果您使用标准分配器,请使用:

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.
}

附录

如果您想让这些模板的生活更轻松,您可以使用别名:

using DefaultTestClass = TestClass<>;

然后这样称呼它:

DefaultTestClass tc3(0, lst2);

http://en.cppreference.com/w/cpp/language/type_alias

【讨论】:

  • 从编译器的消息中,我使用了 TestClass::TestClass(signed char, std::vector, std::allocator) 而不是 TestClass::TestClass(signed char, std ::vector).
  • 是的,但是链接器找不到具有该签名的文件。 :D
  • 如果我重新加载像“TestClass(std::vector,std::uint8_t)”这样的构造函数,并使用“TestClass instance(lst, 0)”,就没有错误。
  • 是的,因为现在您将两个参数传递给具有匹配类型的构造函数,而不是 3。@Chen Dong 请参阅上面的编辑。
  • 是的,我该怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 2011-08-13
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2017-07-25
  • 2019-09-25
相关资源
最近更新 更多