LNK4221: operator<< 重载未在静态库中导出
LNK4221: operator<< overload not exported in static library
尽管有很多关于类似主题的问题,但我找不到能解决我的问题的问题。
我正在使用 Visual Studio 2013 社区版。我有一个包含两个项目的解决方案。一个项目被编译为静态库,另一个是应用程序。应用依赖静态库,编译运行正常
一个 class(.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;
}
啊,我可以看到你做了什么。您认为 ref.cpp 中的函数定义实际上并不是函数定义(即它不生成代码)。它只是一个 模板 函数定义。
为了让这个模板引起代码的生成,你必须实际引用一个模板函数的具体例子。
但是当然在你的 ref.cpp 中没有任何地方这样做,所以当编译 ref.cpp 时没有实例化 operator<<(std::ostream&, const Omni::Ref<T>)
的具体例子。
当您的客户端代码在 Omni::Ref<T>
上为任何 T
调用 operator<<
时,它会完美地生成调用站点代码,因为有模板原型,但没有信息实际创建函数的实现 - 在 ref.cpp 中,客户端代码不可用。
解决方法:
将模板函数的定义放在头文件中。
尽管有很多关于类似主题的问题,但我找不到能解决我的问题的问题。
我正在使用 Visual Studio 2013 社区版。我有一个包含两个项目的解决方案。一个项目被编译为静态库,另一个是应用程序。应用依赖静态库,编译运行正常
一个 class(.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;
}
啊,我可以看到你做了什么。您认为 ref.cpp 中的函数定义实际上并不是函数定义(即它不生成代码)。它只是一个 模板 函数定义。
为了让这个模板引起代码的生成,你必须实际引用一个模板函数的具体例子。
但是当然在你的 ref.cpp 中没有任何地方这样做,所以当编译 ref.cpp 时没有实例化 operator<<(std::ostream&, const Omni::Ref<T>)
的具体例子。
当您的客户端代码在 Omni::Ref<T>
上为任何 T
调用 operator<<
时,它会完美地生成调用站点代码,因为有模板原型,但没有信息实际创建函数的实现 - 在 ref.cpp 中,客户端代码不可用。
解决方法: 将模板函数的定义放在头文件中。