使用模板时无法解析的外部

Unresolved external when using templates

提问人:Tetelu 提问时间:8/8/2011 最后编辑:CommunityTetelu 更新时间:8/8/2011 访问量:423

问:

我正在将运算符重新定义与模板类混合使用,并达到了以下同化:

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)所指出的那样,[解决方案]:未解析的外部符号,带有运算符重载和问题的模板。好友声明应移至类内。

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

C++ 模板 未解析 - 外部

评论

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

答:

0赞 MaximG 8/8/2011 #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;
}

评论

0赞 Tetelu 8/8/2011
我正在使用 VS2005。可能编译器不是原因。