Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

C++: Undefined reference при линковке теста с либой

#cpp #шаблоны_с++ #компоновщик #clang


Вот исходник тесты

#include 
#include 
using namespace RFw;

int main() {
    Array _a_;

    _a_.resize(5);

    _a_[2] = 'b';
    _a_[3] = 'a';

    printf("%c%c\n", *(_a_.provideElement(2)), *(_a_.provideElement(3)));

    return 0;
}

Так компилю:

c++ test.cpp -o test -std=c++11 -Isrc-core/ -Lbin/ -lcore

Вывод:

/tmp/test-k6aFM8.o: In function `main':                                         
                                                                                  
                                                 
test.cpp.text+0x27): undefined reference to `RFw::Array::Array(unsigned int,
int*)'                                                                            
                                              
test.cpp.text+0x3a): undefined reference to `RFw::Array::resize(unsigned int)'
                                                                                  
                                            
test.cpp:(.text+0x52): undefined reference to `RFw::Array::operator[](unsigned
int)'                                                                             
                                              
test.cpp:(.text+0x76): undefined reference to `RFw::Array::operator[](unsigned
int)'                                                                             
                                              
test.cpp:(.text+0x9a): undefined reference to `RFw::Array::provideElement(unsigned
int)'
test.cpp:(.text+0xbd): undefined reference to `RFw::Array::provideElement(unsigned
int)'
test.cpp:(.text+0x101): undefined reference to `RFw::Array::~Array()'
test.cpp:(.text+0x11b): undefined reference to `RFw::Array::~Array()'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

PS Array взят из Array.hpp который инклюдится в common.hpp
Array.hpp:

/**
 *      src-core/Array.hpp
 */
#ifndef _ARRAY_HPP_
#define _ARRAY_HPP_

#include "util.hpp"
#include "Object.hpp"
#include "arrayExceptions.hpp"

namespace RFw {
    template
    class Array : public Object {
    public:
                                Array(intnum _length = 0, TValue* _array = nullptr);
        virtual                 ~Array();

        void                    addToTop(const TValue _element) throw(ArrayOverflowException);
        void                    addToEnd(const TValue _element) throw(ArrayOverflowException);
        void                    clone(const intnum _length, const TValue* _array);

        TValue*                 provideElement(const intnum _index) throw(IndexOutOfRangeException);
        const TValue*           provideElement(const intnum _index) const throw(IndexOutOfRangeException);

        TValue&                 operator[](const intnum _index) throw(IndexOutOfRangeException);
        const TValue&           operator[](const intnum _index) const throw(IndexOutOfRangeException);

        void                    resize(const intnum _newLentgh);

        const Array     getClone() const;
        const intnum            getLength() const;
        const TValue*           getArray() const;
    private:
        intnum                  length__;
        TValue*                 array__;
    };
}

#endif //   _ARRAY_HPP_
    


Ответы

Ответ 1



С шаблонами вы должны помещать реализацию методов в header. В вашем случае пишите так: template class Array : public Object { public: Array(intnum _length = 0, TValue* _array = nullptr) : length__(_length), array__(new TValue[_length]) { // остаток имплементации } virtual ~Array() { delete[] array__; } // и так далее }; Если вы вынесете реализацию методов в .cpp-файл, компилятор не будет знать, какие инстанциации шаблона ему нужно компилировать. Это ограничение модели компиляции языка C++. Sorry for this. Небольшое объяснение. В C++ шаблон не есть класс, это лишь «описание», по которому при подстановке шаблонных аргументов генерируется реальный класс. Никакого объектного кода шаблон сам по себе не производит. Когда компилятор компилирует C++-файл с кодом, использующим шаблон, он видит, с каким шаблонным аргументом используется этот шаблон. Но когда он компилирует C++-файл с реализацией шаблонных методов, он не знает, с какими аргументами инстанциировался шаблон в других файлах, ведь каждый C++-файл компилируется по отдельности! Поэтому решением является положить реализацию внутрь шаблонного класса. При этом компилятор в той точке, где он видит инстанциацию шаблона, видит весь его код, и может скомпилировать все методы класса. (Существует ещё уродливый костыль с указанием в C++-файле точного списка инстанциаций шаблона, который настолько ужасен, что я не хочу о нём и говорить. Аналогом этому было бы около каждой функции указывать заранее список всех аргументов, с которым функция будет вызвана в программе.)

Комментариев нет:

Отправить комментарий