我需要存储指向实例化模板函数的指针,当无法实例化函数时,我想存储指向空函数的指针。我查看了 SFINAE,但我认为它不适用于此处。
struct StaticEntity {
double position;
};
struct DynamicEntity {
double position;
double speed;
};
class MoveSystem {
public:
template <typename T>
void update(T& entity, double dt) {
entity.position += entity.speed*dt;
}
};
typedef void (*updateEntitiesFunc)(void* system, void* entity, double dt);
template <typename S, typename E>
static void update(void* system, void* entity, double dt)
{
// here if inner function cannot be instanced i would like to skip it and do "nothing" instead
((S*)system)->update(*(E*)entity, dt);
}
int main() {
updateEntitiesFunc uf = update<MoveSystem, DynamicEntity>;
updateEntitiesFunc uf2 = update<MoveSystem, StaticEntity>;
//^ this does not compile
// gives error: 'struct StaticEntity' has no member named 'speed'
// i would like it to compile and contain pointer to empty function
return 0;
}
它可能可以通过一些我无法理解的模板魔法来解决。理想情况下不会增加实体类和系统类的复杂性。
设计动机:
对于我所有的实体和系统类型,我想创建一个函数指针的静态数组:
updateEntitiesFunc funcs[EntityTypes::getTypesCount()][SystemTypes::getTypesCount()];
然后在运行时使用类型 ID 调用正确的函数:
funcs[entity->getTypeId()][system->getTypeId()](&system, &entity, dt);
在运行时,我将检查实体是否与系统兼容,但它是运行时信息。因此,必须在编译时为所有实体系统对注册所有函数指针,即使它们不兼容。这是我想创建那些无操作函数的地方。
最佳答案
首先,元编程样板:
namespace details {
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<template<class...>class Z, class, class...Ts>
struct can_apply:
std::false_type
{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:
std::true_type
{};
}
template<template<class...>class Z, class...Ts>
using can_apply=details::can_apply<Z,void,Ts...>;
现在,我们可以检测属性:
template<class T>
using speed_t = decltype(std::declval<T>().speed);
template<class T>
using position_t = decltype(std::declval<T>().position);
template<class T>
using has_speed = can_apply<speed_t, T>;
template<class T>
using has_position = can_apply<position_t, T>;
template<class S, class E>
using update_call_t = decltype( std::declval<S>().update( std::declval<E>(), 0.0 ) );
template<class S, class E>
using has_update = can_apply< update_call_t, S, E >;
我们有三个特征,has_position
, has_update
和 has_speed
这是有用的。
现在我们修复 MoveSystem
:
struct MoveSystem {
template <class T>
std::enable_if_t< has_speed<T&>{} && has_position<T&>{} >
update(T& entity, double dt) {
entity.position += entity.speed*dt;
}
};
接下来,我们修改更新:
namespace updates {
template<class S, class E>
std::enable_if_t< has_update<S,E>{} >
update(S* system, E* entity, double dt ) {
system->update(*entity, dt);
}
void update(void*, void*, double) {}
}
template<class S, class E>
void update(void* system, void* entity, double dt) {
using updates::update;
update(static_cast<S*>(system), static_cast<E*>(entity), dt );
}
检查 .update
使用这些参数的方法。
我启用了 ADL 代码,这样如果类有一个 friend void update( S*, E*, double )
它也会起作用。
这是所有 SFINAE 的工作。请注意,一旦我们有了 can_apply
,就添加更多属性很容易。创建一个别名,生成一个仅在满足属性时才有效的类型,然后写一个 can_apply
将该应用程序转换为编译时 bool 测试的别名。
顺便说一句,MSVC2015 不是 C++11 编译器,因为它无法编译上述代码。在 MSVC 中,您必须找到一些专有扩展才能执行与上述代码等效的操作。这涉及写作 has_position
和其他特征不同。在这种情况下,他们将未能遵守 C++11 标准称为无法执行“表达式 SFINAE”。
请注意,上面使用了一些 C++14 特性。替换 std::enable_if_t<??>
与 typename std::enable_if<??>::type
, 替换 has_position<??>{}
与 has_position<??>::value
如果您的编译器不支持,则进行类似的其他更改。
关于c++ - 当模板函数实例化失败时回退到备用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31302777/
调用 Maven 构建来指定替代文件来代替标准 pom.xml 文件名时是否有参数? 基本上,我需要使用各种配置来运行我的 Maven 构建的测试目标。现在我必须使用外部脚本来使用此配置更新标准 po
基本上我喜欢 PHP 和 SQL 的开发方面。目前我正在处理一个可能需要 MYSQL 复制功能的项目。下面提到的是我的一些要求,只是想知道是否有人可以提供他们的专家建议和提示,以防根据我的需要这是正确
我目前正在做一个教科书中的项目,我遇到了一个 while 循环的模糊问题。课本上的代码如下; while(getImage().getWidth(applet) <= 0); double x = a
如何全局更改Maven的.m2目录的位置? Maven使用${user.home}/.m2进行设置,存储库缓存等。 我知道我可以: 指向存储库缓存的其他目录(通过更改全局配置文件中的localRepo
我正在开发以下代码,一个备用 while 循环: _while = (cond, act) => cond && act() & _while(cond, act) 在这种情况下,act() 旨在每次
到目前为止,我读过的每个教程都说包名应该与您的域相反。但是,如果我没有域并想在市场上发布应用程序怎么办?我可以使用什么备用包命名约定? 最佳答案 随心所欲;这是任意的。 包命名就是为了防止冲突和创建功
您好,我们有一个包含大量 bean、JSP 等的项目。迫切需要在我们的环境中执行自动化测试(我们使用 Maven)。现在,我们可以轻松地为数据库项目层编写测试,为我们实现的各种安全实用程序编写测试。但
这更像是一个 CSS 问题,但我会在此处添加它,因为任何下划线开发人员都可能遇到过它。我有一个索引页面布局: ... ... ... ... 我想用替代文章的类 xyz 定位 div
我正在创建一个 DOM 元素,如下所示; var imgEle = document.createElement('img'); imgEle.src = imgURL;
在应用程序中,当创建特殊类型的对象时,我需要为它们中的每一个生成一个唯一标识。这些对象是通过工厂创建的,并且很有可能在“批量”操作中创建。我意识到框架中的“随机”毕竟不是那么“随机”,所以我尝试按如下
我正在寻找每日备份 sqlite 数据库的正确解决方案。数据库大约 5GB,有规律地增长,每秒接收新数据,并且处于 WAL 模式。该服务是 24/7 全天候服务,因此在备份期间无法停止任何操作。将数据
我正在设置一个多节点 hadoop 集群,并有一个节点之间无密码 SSH 的共享 key 。我将文件命名为 ~/.ssh/hadoop_rsa 并且可以使用 ssh -i ~/.ssh/hadoop_
我的结构如下: blah stuff 它会在整个动态页面中重复几次。我想用两种颜色交替 div 类“post”的背景颜色,但 CSS 的第 nth-child 伪类似乎只适用于直接顺序
例如 Jython 的版本是 2.5.1,这是否意味着它在 2.5.1 版本时与 cpython 语法并行保真? 最佳答案 通常是的,但从技术上讲,没有什么可以阻止替代实现选择他们想要的任何版本号。
我知道 h1 标签对 SEO 很重要,所以我所有的标题都是 H1(太棒了!) 现在,我需要在某些页面上有一个稍微不同的标题(作为文本的第一行)。 通常,我只是将 h1 复制为 h2 并交替使用。 问题
可以为 Perforce 推荐一个类似 P4Win 的替代方案,希望它支持搁置并且可能是开源的?不需要跨平台,只要 Windows 就可以了。 我这么问是因为我不喜欢新的 P4V 界面,而且我发现 P
大家好,提前寻求帮助:我正在尝试将第二个标题添加到自定义临时页面,并在该备用标题中添加一个不同于 style.css 的备用 css 文件。 我像这样从 cat 模板页面调用了自定义 header
我在这里遇到了一些麻烦。我想在鼠标悬停在 div 之后显示图像。 HTML: CSS: #testmouseover { left: -9px; top: -9px;
这个问题在这里已经有了答案: How do I switch my CSS stylesheet using jQuery? (5 个答案) 关闭 9 年前。
有人知道是否有一些用于 Direct X 的替代 API,我的意思是只是 GUI 库!没有像我们在 DXUT 中那样重新实现 Direct X。 最佳答案 对于 Windows 10 上的 Windo
我是一名优秀的程序员,十分优秀!