用于回调注册的 SFINAE
SFINAE for callback registration
>我尝试使用此技巧注册回调(如果存在),请使用enable_if检查成员是否存在:
template<class Callback>
class Foo
{
public:
Foo()
{barEventRegister(has_member{});}
private:
struct has_not_member{};
struct has_member:public has_not_member{};
template<class X> struct cb_test
{typedef int type;};
template<typename cb_test<decltype(&Callback::barEvent)>::type=0>
void barEventRegister(has_member)
{
//register callback for bar
}
void barEventRegister(has_member)
{
//do nothing
}
};
struct MyCallback
{
};
int main()
{
Foo<MyCallback> foo;
}
但我得到
template<typename cb_test<decltype(&Callback::barEvent)>::type=0>
void barEventRegister(has_not_member)
error: 'barEvent' is not a member of 'MyCallback'
似乎无论如何都会实例化无效的模板。这是因为Callback
是类模板的一部分,而不是注册例程吗?
SFINAE 失败,因为它依赖于周围的类类型参数。SFINAE 仅适用于推导的类型参数,这些参数是编译器试图根据调用找出的函数类型参数。
修复可能如下所示:
template<class S = Callback, typename cb_test<decltype(S::barEvent)>::type=0>
void barEventRegister(has_member)
其中 SFINAE 基于 S,编译器将推导出来而不是显式获取。
另外,请注意,您的第二次重载应该需要has_not_member
,而不是has_member
。就像现在一样,即使成员存在,也将始终选择它,因为当等效于模板重载时,会选择非模板重载。
相关文章:
- 无法将结构注册为增强几何体3D点
- 为什么使用SFINAE而不是函数重载
- 如何使用模板函数的函数签名进行SFINAE
- 数据成员SFINAE的C++17测试:gcc vs clang
- 使用在用于SFINAE的void_t中具有参数的方法
- 如何使用AngelScript注册SFML Vector2运算符
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 在遍历处理程序的向量时注册和注销处理程序
- 有没有任务栏API可以立即应用注册表更改
- 使用QJsEngine在Qt中注册自定义类型
- 提供与TMP和SFINAE的通用接口
- 检查注册表项是否链接到(或副本)另一个注册表项
- "Inverse SFINAE"避免模棱两可的过载
- 如何使用 TStyleManager::UnRegisterStyle() 取消注册样式
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- SFML 碰撞永远不会在我的系统中注册
- 尝试从C++访问 UWP 的电子邮件邮件类会导致"REGDB_E_CLASSNOTREG类未注册"错误
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 用于回调注册的 SFINAE
- 带有继承历史的CRTP插件自动注册(尝试使用SFINAE,但失败)