1

尽管有类似主题的许多问题,但我无法找到解决我的问题的问题。LNK4221:运算符<<过载未在静态库中导出

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

一个类(.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; 
} 
+0

你如何使用这个'Omni'命名空间?您可以创建一个[最小,完整和可验证示例](http://stackoverflow.com/help/mcve)并向我们展示? – 2015-04-03 15:40:26

+0

@JoachimPileborg这不是一个合理的步骤,这是一个很好的例子。 – Grault 2015-04-03 16:01:14

回答

2

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

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

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

当你的客户端代码调用的Omni::Ref<T>任何Toperator<<,它产生的通话站点代码非常清楚,因为有一个模板雏形,但目前还没有信息实际上是创建函数的实现 - 这是在ref.cpp其中不适用于客户端代码。

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

+0

我在发布后直接注意到了这一点。 >。<感谢您对它的重要性的精确解释。 – Grault 2015-04-03 15:57:13