Как решить неожиданный std::allocator при компиляции кода?

Я определил конструктор класса, как показано ниже:

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

Затем я хочу использовать тест Google для выполнения модульного теста, ошибка компиляции возникает, когда я пытаюсь создать экземпляр 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‹ Type, std::allocator‹ Type>)’ collect2: error: ld вернул 1 статус выхода»

Ниже моя среда:

версия g++: 5.3.0
тестовая версия google: 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‹ Element, std::allocator‹ Element > >)'
collect2: error: ld вернул 1 статус выхода


person Chen Dong    schedule 06.04.2017    source источник
comment
Опубликуйте минимально воспроизводимый пример.   -  person cpplearner    schedule 06.04.2017
comment
извините, из-за соглашения о конфиденциальности я не могу показать вам полный код. И, на мой взгляд, приведенного выше сообщения об ошибке достаточно, чтобы описать мою ситуацию, и вы должны иметь возможность понять проблему. (Вышеприведенный код представляет собой абстрактную модель моего исходного кода)   -  person Chen Dong    schedule 06.04.2017
comment
@ChenDong Не полный код, а минимальный код, который по-прежнему показывает ту же ошибку.   -  person user4815162342    schedule 06.04.2017
comment
Нет, этого недостаточно. Во-первых, это даже не полное сообщение о сборке, но я предполагаю, что оно пришло на этапе ссылки. Это означает, что ошибка может быть в определении TestClass или в том, как вы его используете. И вы уверены, что uint8_t и signed char имеют один и тот же тип (а не просто имеют одинаковое представление) в вашей системе?   -  person Serge Ballesta    schedule 06.04.2017
comment
@stackoverflow.com/users/3545273/serge-ballesta Да, я обновляю минимальный код. Пожалуйста, помогите мне решить эту проблему,   -  person Chen Dong    schedule 06.04.2017
comment
@stackoverflow.com/users/4672588/cpplearner Да, я обновляю минимальный код. Пожалуйста, помогите мне решить эту проблему   -  person Chen Dong    schedule 06.04.2017


Ответы (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>)

в качестве конструктора достаточно, если вы используете стандартный аллокатор типа "Тип"..

См.: 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

person MABVT    schedule 06.04.2017
comment
Из сообщения компилятора я использовал TestClass::TestClass(signed char, std::vector‹ Type›, std::allocator‹ Type›), а не TestClass::TestClass(signed char, std::vector‹ Type›). - person Chen Dong; 06.04.2017
comment
Да, но компоновщик не может найти файл с такой подписью. :D - person MABVT; 06.04.2017
comment
И если я перезагружу конструктор, например TestClass(std::vector‹Type›,std::uint8_t), и использую экземпляр TestClass(lst, 0), ошибки не будет. - person Chen Dong; 06.04.2017
comment
Да, потому что теперь вы передаете конструктору два параметра с соответствующими типами, а не 3. @Chen Dong, пожалуйста, см. правку выше. - person MABVT; 06.04.2017
comment
Да, так что мне делать? - person Chen Dong; 06.04.2017
comment
Прочитайте две приведенные выше ссылки из редактирования, и вы будете знать, что делать: D - person MABVT; 06.04.2017
comment
Я извиняюсь, что отправил неправильное сообщение, и сейчас я его исправляю. И сообщение об ошибке - это неопределенная ссылка на TestClass::TestClass(signed char, std::vector‹ Type, std::allocator‹ Type›), это не 3 параметра, а 2. - person Chen Dong; 06.04.2017