c++ - Unresolved external 使用带有 copy-and-swap 的模板类

标签 c++ templates unresolved-external copy-and-swap

在使用模板类时遇到链接器错误,我尝试按照此处的建议实现 copy-and-swap 习惯用法:

What is the copy-and-swap idiom?

模板类,我们称之为“TemplateClass”,其部分定义如下:

template< class T >
class TemplateClass
{
    // ...
    TemplateClass< T >& operator= ( TemplateClass< T > other );
    friend void swap( TemplateClass< T >& first, TemplateClass< T >& second );
    // ...
};

我已将实现放在单独的 TemplateClass.cpp 中,该模板包含在 .h 文件中。 (编辑:如果所有内容都在 .h 文件中,我也会遇到同样的问题)

赋值运算符定义为:

template< class T >
TemplateClass< T >& TemplateClass< T >::operator= ( TemplateClass< T > other )
{
    // copy-and-swap idiom
    swap( *this, other );
    return *this;
}

交换方法定义为:

template< class T >
void swap( TemplateClass< T >& first, TemplateClass< T >& second )
{
    using namespace std;
    swap( first.member1, second.member1 );
    swap( first.member2, second.member2 );
    // ...
}

(别担心,我并没有真正将我的成员命名为“member1”等)

我有一个类似的类,它以相同的方式定义,但不是模板类。那里一切正常。 但是,如果我有课 TestClass其中有一个成员TemplateClass< HandledClass > member我在其方法之一中进行调用,例如

void TestClass::setMember( TemplateClass< HandledClass > newObject )
{
    member = newObject;
}

我收到 Unresolved external 错误:

LNK2019:函数“public: class TemplateClass X & __thiscall TemplateClass X::operator=(class TemplateClass)”(. ..) 在 TestClass.obj 中

或者换句话说: TestClass中的东西来电 TemplateClass<HandledClass>::operator=没有找到void swap( TemplateClass<HandledClass>, TemplateClass<HandledClass> ) .

所以我的问题是: 为什么运算符(operator)找不到交换方法?

看起来它没有针对模板参数进行编译。是否有可能让编译器也编译 friend void?

我可能会放弃 friend void方法并定义一个类内交换方法加上一个类外交换方法加上 std 命名空间中的一个,但我不知道它是否会以这种方式工作,并且如果可能的话我想避免这种情况。


解决方案:

这完成了工作:

template< class t >
class TemplateClass
{
    friend void swap( TemplateClass& first, TemplateClass& second )
    {
        // ...
    }
};

请注意我如何也删除 < T > 出现的地方。

最佳答案

这是将非成员函数与模板融为一体时的常见问题。 friend TemplateClass内的声明不与你的swap交 friend 模板,而是一个非模板化的自由函数 swap这需要TemplateClass<T>永远T模板被实例化(即特化 TemplateClass<int> 将与未模板化的自由函数 void swap( TemplateClass<int>&,TemplateClass<int>& ); 成为 friend )。

最好的解决方案是提供 swap定义内联在类模板定义中,因为这将使编译器生成非模板化 swap在需要时提供精确类型的函数。作为另一个积极的副作用,swap函数只会在参数相关查找期间找到,因此它不会参与任何不涉及模板的重载解析。

其他替代方案正在与整体成为 friend swap模板函数,或与 swap 的特定特化成为 friend 应用于相同的函数 T模板已被实例化。第一个选项的代码很简单,但它授予对 swap 的所有特化的访问权限。模板,这可能会产生不好的副作用。与特定的人交 friend swap特化解决了这个问题,但实现起来有点复杂(您需要向前声明类模板,然后声明 swap 模板,然后定义类模板,最后定义 swap 模板)。

有关此内容的更多信息,请参阅其他 answer ,其中更详细地解释了不同的选项和语法。

关于unresolved external的具体错误信息,这是由于标识符查找的工作方式决定的。当您使用swap(*this,other);时在成员函数内部,查找在类内部开始,并尝试找到合适的 swap 。它首先在类上下文中查找并找到friend的声明。自由函数,因此查找不会继续向外并添加对该特定自由函数的依赖关系。它添加依赖项并等待链接器找到适当的符号。因为编译器从未考虑过模板化的 swap在命名空间级别,它从未实际实例化它,但即使它实例化了该模板, operator= 内的依赖项成员函数是一个自由函数,没有那么特化。

关于c++ - Unresolved external 使用带有 copy-and-swap 的模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7331085/

相关文章:

c++ - 未定义的行为和顺序点

c++ - typedef - 原始类型到原始类型

c++ - 我如何以通用方式打印任何容器的内容?

c++ - 当所有内容都在一个文件中时,为什么我会收到链接器错误?

c++ - 什么是 undefined reference /未解析的外部符号错误,我该如何解决?

c++ - VC++ LNK2019 错误我似乎无法修复

c++ - 在类中创建静态变量 (C++)

c++ - 在这里将 random_generator 设置为静态有什么问题吗?

javascript - 如何在 Iron Router Meteor 中查看当前路线

c++ - 简单类中的 LNK2019 错误,看不出原因