c++ - 将混合类(模板化和非模板化函数)编译到静态库中
问题描述
为了科学,我正在编写一个游戏引擎库。我过去成功地编写了静态库,尽管没有模板函数。
在处理模板化函数时,我习惯将它们的代码与非模板化的代码分开。模板函数代码位于头文件中,而其他函数代码位于 .cpp/.hpp 文件中。
下面是其中一个模块的片段:信号。
// Connection.h
#pragma once
#include <memory>
#include <functional>
namespace mqs
{
using Disconnector = std::function<void(std::uint32_t)>;
class Connection final
{
public:
explicit Connection(std::shared_ptr<mqs::Disconnector> disconnector, std::uint32_t index);
bool connected() const;
void disconnect() const;
private:
std::uint32_t index;
std::weak_ptr<mqs::Disconnector> disconnector;
};
}
// Signal.h
#pragma once
#include <vector>
#include "connection.hpp"
namespace mqs
{
template <typename...>
class Signal;
template <typename R, typename... A>
class Signal<R(A...)> final
{
public:
Signal();
template <typename Lambda>
mqs::Connection connect(Lambda&& lambda) {
slots.push_back(std::forward<Lambda>(lambda));
return mqs::Connection(disconnector, slots.size() - 1U);
}
void operator()(A&&... args) const;
unsigned connections() const;
private:
std::vector<std::function<R(A...)>> slots;
std::shared_ptr<mqs::Disconnector> disconnector;
};
}
// Connection.hpp
#pragma once
#include "connection.h"
namespace mqs
{
Connection::Connection(std::shared_ptr<mqs::Disconnector> disconnector, std::uint32_t index) {
this->index = index;
this->disconnector = disconnector;
}
bool Connection::connected() const {
return !disconnector.expired();
}
void Connection::disconnect() const {
if (const auto& lock = disconnector.lock()) {
lock->operator()(index);
}
}
}
// Signal.hpp
#pragma once
#include "signal.h"
namespace mqs
{
template <typename R, typename... A>
Signal<R(A...)>::Signal() {
disconnector = std::make_shared<mqs::Disconnector>([this](std::uint32_t index) {
slots.erase(slots.begin() + index);
});
}
template <typename R, typename... A>
void Signal<R(A...)>::operator()(A&&... args) const {
for (auto& slot : slots) {
slot(std::forward<A>(args)...);
}
}
template <typename R, typename... A>
unsigned Signal<R(A...)>::connections() const {
return slots.size();
}
}
它可以编译,但我一直在处理的问题之一是mqs::Signal
(signal.hpp) 不能包含在不同的头文件中,否则会导致function already has a body
. 当包括在内时,signal.h
我明白unresolved external symbol
这是有道理的。
我也尝试过inline
在上面的 .hpp 文件中定义所有函数。
除了使用巨大的仅标头方法之外,还有什么方法可以实现这一点?
解决方案
正如您已经知道的那样,您需要制作功能模板inline
。这是必要的,因为模板首先需要被实例化为可编译的函数,这意味着编译器需要源代码。
但是,如果您查看类似 的成员Signal<R(A...)>::disconnector;
,您会注意到它们不依赖于R
or A...
。因此,您可以将它们移动到非模板基类。
.ipp
对于仍然需要包含的实现文件使用扩展名有一个相当普遍的约定,例如因为它们包含模板代码。这些通常会包含在相应的.hpp
文件中,就在#endif
标头保护之前。因此,.ipp
文件不需要自己的标头保护。
推荐阅读
- swift - 在没有颤振视图控制器的情况下在本机和颤振之间发送数据
- java - 如何将视频从一个应用程序共享到另一个应用程序?
- c# - 为 WCF 服务设置 WSSE
- java - 全屏应用程序中的警报问题
- express - Express js ip 规范化
- r - R在每张表上应用row_to_names函数后合并多个excel表
- c++ - 如何使用多次调用的 openssl evp_encryptupdate 进行加密?
- php - HTML视频音频工作但视频为空白
- swift - HKLiveWorkoutDataSource - 如何跟踪 ElevationAscended 和 ElevationDescended?
- java - 没有从日历中选择日期..我已经解决了这个问题。问题已解决