我正在编写一个 实体组件系统游戏引擎。作为其中的一部分,我已经编写了一个
如评论中所述,我在
我的问题是:是否可能将此检查移动到编译时,而不是等待运行时?似乎在运行时应该有足够的信息来做出这个决定。
到目前为止,我已经探索/阅读了与SFINAE相关的内容,这似乎是要采取的方法,但我无法弄清楚如何使这些惯用语在这种特定情况下起作用。此链接提供了基本SFINAE惯用语的良好概述,此SO问题提供了一些很好的代码片段,最后此博客文章似乎几乎涵盖了我的确切情况。
以下是一个完整示例,其中包含我尝试实现这些链接中找到的信息:
Manager
类,该类将注册各种 IBase
实现,并稍后允许我实例化这些实现。下面是我希望使用它的示例。class Manager{
public:
template<class T>
void registerDerived()
{ /*Register a Derived with the Manager*/ };
template<class T>
T createDerived()
{ /*if T is not registered, throw an error*/
return T();};
};
struct IBase{
};
struct Derived1 : public IBase{
};
struct Derived2 : public IBase{
};
如评论中所述,我在
template<class T>Manager::createDerived()
中的代码检查了是否使用template<class T>Manager::registerDerived()
注册了Base
的特定实现,如果没有注册,则会抛出错误。这个检查很简单,为了保持简单性,代码示例中省略了它。我的问题是:是否可能将此检查移动到编译时,而不是等待运行时?似乎在运行时应该有足够的信息来做出这个决定。
到目前为止,我已经探索/阅读了与SFINAE相关的内容,这似乎是要采取的方法,但我无法弄清楚如何使这些惯用语在这种特定情况下起作用。此链接提供了基本SFINAE惯用语的良好概述,此SO问题提供了一些很好的代码片段,最后此博客文章似乎几乎涵盖了我的确切情况。
以下是一个完整示例,其中包含我尝试实现这些链接中找到的信息:
#include <iostream>
class Manager{
public:
template<class T>
void registerDerived()
{ /*Register a Derived with the Manager*/ }
template<class T>
T createDerived()
{ /*if T is not registered, throw an error*/
return T();}
};
struct IBase{
};
struct Derived1 : public IBase{
};
struct Derived2 : public IBase{
};
template<typename T>
struct hasRegisterDerivedMethod{
template <class, class> class checker;
template <typename C>
static std::true_type test(checker<C, decltype(&Manager::template registerDerived<T>)> *);
template <typename C>
static std::false_type test(...);
typedef decltype(test<T>(nullptr)) type;
static const bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
};
int main(){
Manager myManager;
myManager.registerDerived<Derived1>();
// whoops, forgot to register Derived2!
Derived1 d1 = myManager.createDerived<Derived1>(); // compiles fine, runs fine. This is expected.
Derived2 d2 = myManager.createDerived<Derived2>(); // compiles fine, fails at runtime (due to check in createDerived)
std::cout << std::boolalpha;
// expect true, actual true
std::cout << "Derived1 check = " << hasRegisterDerivedMethod<Derived1>::value << std::endl;
// expect false, actual true
std::cout << "Derived2 check = " << hasRegisterDerivedMethod<Derived2>::value << std::endl;
return 0;
}
**
简述
如何修改上述代码以产生编译时错误(可能使用 static_assert
),而不是等到运行时才检测到错误?
**
constexpr
对象并同时在编译时读取该状态。 - WhiZTiMManager
是一个单例模式吗? - Waltercreate()
替换为后跟create()
的register()
有什么问题(但在一个函数调用中完成)?假设多个register<T>()
不会引起任何问题。 - Walter