【问题标题】:Unresolved external when using templates使用模板时未解决的外部问题
【发布时间】:2011-10-21 21:17:44
【问题描述】:

我正在将运算符重定义与模板类混合,并达到以下分配:

j = end - begin;

在我的main函数中,变量类型如下:

ptrdiff_t j;
util::BaseArrayIterator<int, 6> begin, end;

Begin 和 end 已从 util::BaseArray: 初始化:

util::BaseArray<int, 6> ba(SOME_PARAMETERS);
begin = ba.begin(); end = ba.end();

BaseArrayIterator 是一种自行实现的迭代器类型。

我得到错误:

TestProject.obj : error LNK2019: unresolved external symbol
"int __cdecl util::operator-(class util::BaseArrayIterator<int,6>
const &,class util::BaseArrayIterator<int,6> const &)" 
(??Gutil@@YAHABV?$BaseArrayIterator@H$05@0@0@Z) referenced in
function _main

由于消息中的第一个代码语句(删除它可以解决问题)。

我已经包含了一个包含以下定义和声明的头文件:

namespace util {
template<typename T, int n>
typename BaseArrayIterator<T,n>::difference_type operator -
    (const BaseArrayIterator<T,n> &itL,
     const BaseArrayIterator<T,n> &itR);
...
template<typename T, int n>
typename BaseArrayIterator<T,n>::difference_type operator -(
    const BaseArrayIterator<T,n> &itL, 
    const BaseArrayIterator<T,n> &itR)
{   return -(itL.m_cnt - itR.m_cnt);
}
}

导致问题的原因是什么? 编译器报告搜索 util::operator -,所以他确实找到了声明,但没有找到定义,尽管它们在同一个文件中。而且我没有看到签名错误。

--- 编辑说明 ------------------------------------------ ----------------------------------

更换

end-begin

util::operator-<int, 6>(end,begin)

解决了问题,但我不想每次都明确指定参数。简洁是支持重载运算符的主要论据之一,所以我想使用经典的短格式。

--- 编辑注释 2 ----------------------------------------- ----------------------------------

正如 Nicola Mussatti 亲切地指出的那样,[解决方案]:Unresolved external symbol with operator overloading and templates 问题就在这里。朋友声明应该移到类中。

所以我做到了,我都笑了。 现在再次将它们分开会产生一个模棱两可的过载问题,这与以前的错误不同。

【问题讨论】:

  • 尝试将声明与定义放在单独的文件中。模板是 C++ 中非常微妙的东西。试着改变一些东西,直到它工作正常。
  • 分离声明和定义只会让事情变得更糟。
  • 会不会是定义在命名空间之外? } 放错地方了?
  • 我的代码片段中缺少结束 }。我已经添加了。
  • 我模糊地记得存在与将类模板作为参数并在自定义命名空间中定义的运算符的实例化相关的问题,即使它与定义其参数类型的命名空间相同。您可以尝试将您的运算符定义移动到您的类模板中并将其声明为朋友吗?

标签: c++ templates unresolved-external


【解决方案1】:

您使用的是哪个编译器?

VS2010 对这段代码很满意:

namespace util
{
    template<typename T>
    class BaseArrayIterator
    {
    public:
        typedef ptrdiff_t difference_type;

        int pos;
        T x;
    };

    template<typename T>
    typename BaseArrayIterator<T>::difference_type operator -
        (const BaseArrayIterator<T> &itL,
         const BaseArrayIterator<T> &itR);

    template<typename T>
    typename BaseArrayIterator<T>::difference_type operator -
        (const BaseArrayIterator<T> &itL,
         const BaseArrayIterator<T> &itR)
    {
        return itL.pos - itR.pos;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    util::BaseArrayIterator<int> a;
    util::BaseArrayIterator<int> b;

    ptrdiff_t dist = a - b;
    return 0;
}

【讨论】:

  • 我正在使用 VS2005。可能编译器不是原因。