首页 > 解决方案 > 为什么显式模板实例化不起作用?

问题描述

我在头文件和代码文件中声明了一个类。

共享资源管理器.h

#ifndef SharedResourceManager_H_
#define SharedResourceManager_H_

#include <mutex>

namespace find_object {

    template <class T>
    class SharedResourceManager {
        public:
            SharedResourceManager();
            SharedResourceManager(T* resource);
            ~SharedResourceManager();
            T* checkOutResource() const;
            void checkInResource() const;
            void updateResource(T* resource);
        private:
            T* _resource;
            std::mutex lock;
    };
    extern template class SharedResourceManager<std::string>;
}
#endif

共享资源管理器.cpp

#include "SharedResourceManager.h"

using namespace find_object;


template <class T>
SharedResourceManager<T>::SharedResourceManager() 
{
    this->_detector = NULL;
}

template <class T>
SharedResourceManager<T>::SharedResourceManager(T* resource)
{
    this->_resource = resource;
}

template <class T>
SharedResourceManager<T>::~SharedResourceManager()
{
    delete this->_resource;
}

template <class T>
T* SharedResourceManager<T>::checkOutResource() const
{
    this->lock.lock(); //Lock the detector until released with checkInDetector
    return this->_resource;
}

template <class T>
void SharedResourceManager<T>::checkInResource() const
{
    this->lock.unlock();
}

template <class T>
void SharedResourceManager<T>::updateResource(T* resource) {
    this->lock.lock();
    delete this->_resource;
    this->_resource = resource;
    this->lock.unlock();
}

namespace find_object {
    template class SharedResourceManager<std::string>;
}

例子.cpp

#include "SharedResourceManager.h"
#include <iostream>

using namespace std;
namespace find_object {

    void func() {
        std::string orig = "resource";
        SharedResourceManager<std::string> srm(&orig);
        std::string* resource = srm.checkOutResource();
        cout << "Shared Resource Manager Created" << *resource << endl;
        srm.checkInResource();
    }
}

int main() {
    find_object::func();
    return 1;
}

我正在尝试在 example.cpp 中使用这个模板类。我尝试使用我需要的类显式实例化模板,但在编译时仍然出现以下链接器错误:g++ example.cpp

/tmp/ccfssejJ.o: In function `find_object::func()':
example.cpp:(.text+0x56): undefined reference to `find_object::SharedResourceManager<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::SharedResourceManager(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
example.cpp:(.text+0x62): undefined reference to `find_object::SharedResourceManager<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::checkOutResource() const'
example.cpp:(.text+0xac): undefined reference to `find_object::SharedResourceManager<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::checkInResource() const'
example.cpp:(.text+0xb8): undefined reference to `find_object::SharedResourceManager<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~SharedResourceManager()'
example.cpp:(.text+0xff): undefined reference to `find_object::SharedResourceManager<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~SharedResourceManager()'
collect2: error: ld returned 1 exit status

我正在使用 catkin build 进行构建。为什么我会收到此错误?

标签: c++templates

解决方案


首先,源文件中的显式实例化必须与模板出现在同一个命名空间中,using 指令不会将其删除。因此,您需要将源文件修改为:

namespace find_object {
    template class SharedResourceManager<Feature2D>;
}

除此之外,您可能需要在标头中明确的模板实例化声明

template <class T>
class SharedResourceManager {
  // as before
};

// Need to add this
extern template class SharedResourceManager<Feature2D>;

这指示编译器不要隐式实例化类模板,因为实例化在别处。


推荐阅读