LNK4221:运算符<<重载未导出到静态库中

LNK4221: operator<< overload not exported in static library

本文关键字:lt 静态 重载 运算符 LNK4221      更新时间:2023-10-16

尽管有很多关于类似主题的问题,我还是找不到一个能解决我问题的。

我使用的是Visual Studio 2013社区版。我有一个包含两个项目的解决方案。一个项目被编译为静态库,另一个是应用程序。应用程序依赖于静态库,并且它编译和运行良好。

链接器忽略了一个类(.cpp/.h对),特别是Ref(底部列出的源)。根据我的编译输出,ref.cpp是在namespace.cpp之前编译的。namespace.cp间接包含ref.h,这可能会导致链接器的先进先出行为忽略ref

我有一个操作员的过载<lt;在参考文献cpp和参考文献h中。为什么它似乎被忽视了

warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library  [...]OmniCoreref.obj  Core

参考文献h.

#ifndef REF_H
#define REF_H
#include <memory>
#include <ostream>
namespace Omni
{
    template<typename T>
    using Ref = std::shared_ptr<T>;
}
template<typename T>
std::ostream & operator<<(std::ostream & s, const Omni::Ref<T> type);
#endif // REF_H

(我知道using namespace Omni;排除了对Omni::的需要,但在调试时,我喜欢加倍确定。)

参考.cpp

#include "ref.h"
using namespace Omni;
template<typename T>
std::ostream & operator<<(std::ostream & s, const Omni::Ref<T> value)
{
    return s << *value;
}

啊,我能看到你做了什么。你认为ref.cpp中的函数定义实际上并不是函数定义(即它不生成代码)。它只是一个模板函数定义。

为了让这个模板生成代码,您必须实际引用一个模板函数的具体示例。

当然,在ref.cpp中没有任何地方能做到这一点,所以在编译ref.cpp时,没有实例化operator<<(std::ostream&, const Omni::Ref<T>)的具体示例。

当您的客户端代码在Omni::Ref<T>上为任何T调用operator<<时,它会很好地生成调用站点代码,因为有一个模板原型,但没有实际创建函数实现的信息-这在ref.cpp中,客户端代码不可用。

解决方案:将模板函数的定义放入头文件中。