c++ - 指向未知模板类型的全局外部指针
问题描述
背景:
我有一个游戏引擎,其中有几个extern
指向各种子系统的 ed 全局指针,以便下游游戏应用程序易于访问:
#pragma once
#include <type_traits>
class JobSystem;
class FileLogger;
class Renderer;
class Console;
class Config;
class UISystem;
class InputSystem;
class AudioSystem;
class EngineSubsystem;
class GameBase;
extern JobSystem* g_theJobSystem;
extern FileLogger* g_theFileLogger;
extern Renderer* g_theRenderer;
extern Console* g_theConsole;
extern Config* g_theConfig;
extern UISystem* g_theUISystem;
extern InputSystem* g_theInputSystem;
extern AudioSystem* g_theAudioSystem;
extern GameBase* g_theGame;
extern EngineSubsystem* g_theSubsystemHead;
template<typename GameDerived>
GameDerived* GetGameAs() noexcept {
static_assert(std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameBase>>>, std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameDerived>>>>);
return dynamic_cast<GameDerived*>(g_theGame);
}
问题:
我希望能够提供一个指向App
该类的全局指针,但该类是一个模板这一事实使得难以理解如何实现它。
伪代码实现:
类层次结构:
#pragma once
#include <type_traits>
class GameBase { /*...*/ }
class Game : public GameBase { /*...*/ }
template<typename GameType>
class App {
static_assert(std::is_base_of_v<GameBase, GameType>, "Template type GameType not derived from GameBase.");
public:
static void CreateApp() {
if(_theApp) {
return;
}
_theApp = new App<T>();
}
static void DestroyApp() {
if(!_theApp) {
return;
}
delete _theApp;
_theApp = nullptr;
}
//...
private:
void SetupSubsystemPointers() {
//...
_theRenderer = std::make_unique<Renderer>();
g_theRenderer = _theRenderer.get();
//...
_theGame = std::make_unique<GameType>();
g_theGame = _theGame.get();
//...This does not work:
//g_theApp = this;
}
std::unique_ptr<JobSystem> _theJobSystem{};
std::unique_ptr<FileLogger> _theFileLogger{};
std::unique_ptr<Config> _theConfig{};
std::unique_ptr<Renderer> _theRenderer{};
std::unique_ptr<Console> _theConsole{};
std::unique_ptr<InputSystem> _theInputSystem{};
std::unique_ptr<UISystem> _theUI{};
std::unique_ptr<AudioSystem> _theAudioSystem{};
std::unique_ptr<GameType> _theGame{};
//I would really like this to be a std::unique_ptr.
static inline App<GameType>* _theApp{};
}
这是我在实现指向 App 类的全局指针时遇到的麻烦。
通用标题:
#pragma once
#include <type_traits>
class JobSystem;
class FileLogger;
class Renderer;
class Console;
class Config;
class UISystem;
class InputSystem;
class AudioSystem;
class EngineSubsystem;
class GameBase;
extern JobSystem* g_theJobSystem;
extern FileLogger* g_theFileLogger;
extern Renderer* g_theRenderer;
extern Console* g_theConsole;
extern Config* g_theConfig;
extern UISystem* g_theUISystem;
extern InputSystem* g_theInputSystem;
extern AudioSystem* g_theAudioSystem;
extern GameBase* g_theGame;
// WHAT DO I NEED TO DO TO GET SOMETHING LIKE THE FOLLOWING TO WORK?
//extern App* g_theApp;
//I tried
//template<typename GameType>
//App<GameType>* g_theApp but compilation failed with an undefined variable error or template vomit errors.
//extern GameType* g_theGame; //This would be nice to have. It would replace the above GameBase pointer and the below GetGameAs function
extern EngineSubsystem* g_theSubsystemHead;
template<typename GameDerived>
GameDerived* GetGameAs() noexcept {
static_assert(std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameBase>>>, std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameDerived>>>>);
return dynamic_cast<GameDerived*>(g_theGame);
}
常见实现:
#include "Engine/Core/EngineCommon.hpp"
JobSystem* g_theJobSystem = nullptr;
FileLogger* g_theFileLogger = nullptr;
Renderer* g_theRenderer = nullptr;
Console* g_theConsole = nullptr;
Config* g_theConfig = nullptr;
UISystem* g_theUISystem = nullptr;
InputSystem* g_theInputSystem = nullptr;
AudioSystem* g_theAudioSystem = nullptr;
GameBase* g_theGame = nullptr;
EngineSubsystem* g_theSubsystemHead = nullptr;
//DOES NOT WORK
//App* g_theApp = nullptr;
解决方案
template<typename GameType> App<GameType>* g_theApp;
应该为你工作。看起来您忘记在公共标头中转发声明 App,这就是您无法声明指向它的指针的原因。
此外,如果您可以使用 C++17,您可以停止使用extern
并开始使用inline
所有变量声明,并将它们转换为类似的定义
inline JobSystem* g_theJobSystem = nullptr;
inline FileLogger* g_theFileLogger = nullptr;
inline Renderer* g_theRenderer = nullptr;
inline Console* g_theConsole = nullptr;
inline Config* g_theConfig = nullptr;
inline UISystem* g_theUISystem = nullptr;
inline InputSystem* g_theInputSystem = nullptr;
inline AudioSystem* g_theAudioSystem = nullptr;
inline GameBase* g_theGame = nullptr;
inline EngineSubsystem* g_theSubsystemHead = nullptr;
inline
将告诉编译器可以在多个翻译单元中定义变量,链接器会将它们全部合并为一个,就像它对内联函数所做的那样。
推荐阅读
- google-data-studio - 如何在 Google 数据工作室日期范围过滤器中包含所有数据
- google-data-studio - 在 Google Data Studio 中按类别而不是日期创建饼图
- python - 使用 Python 和 Cx_Oracle 调用带有 XMLTYPE 输入和输出参数的 Oracle 存储过程
- vue.js - 使用 vue.js 从 textfield 和 textarea 中删除 null
- sql - 如何查询三列并且总共只有一列?
- excel - Excel - 在过滤器之后动态命名表格的左上角单元格
- python - 连接pyspark中多列的通用合并
- ios - CLLocationManager 授权回调(当没有 auth-change 时)
- jenkins - 更改 Jenkins 状态颜色或提供消息
- r - 如何计算一列中的值与另一列中的值不匹配的比例?