LNK4221:运算符<<过载未在静态库中导出

时间:2015-04-03 15:34:47

标签: c++ visual-studio visual-studio-2013 linker operator-overloading

尽管有很多关于类似主题的问题,但我找不到解决我问题的问题。

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

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

我有一个运算符重载<<在ref.cpp和ref.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  [...]Omni\Core\ref.obj  Core

ref.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::的需要,但在调试中我喜欢双重确认。)

ref.cpp

#include "ref.h"

using namespace Omni;

template<typename T>
std::ostream & operator<<(std::ostream & s, const Omni::Ref<T> value)
{
    return s << *value;
}

1 个答案:

答案 0 :(得分:2)

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

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

但是当然在你的ref.cpp中没有这样做,所以当编译ref.cpp时,没有实例化operator<<(std::ostream&, const Omni::Ref<T>)的具体例子。

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

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