c++ - 根据虚拟方法的存在,有条件地将 mixin 应用于接口
问题描述
我有一堆类似的接口。我有一个可以实现这些接口并实现这些接口通用的大多数操作的类模板。因此,我在这些接口之上使用了一个 mixin。
不幸的是,其中一些接口缺少一些常用方法。
struct Intf1
{
virtual void f() = 0;
};
struct Intf2 {}; // Missing f.
我想应用一个mixin
template <class T>
struct Mixin
: public T
{
virtual void f() override {};
};
到一个基类,如果基类声明了一个f
被mixin覆盖的虚方法。所以,基本上我正在寻找一些元编程技术
template <template <class> class Mixin, class T> using Magic = ...;
这Magic<Mixin, Intf1>
就是Mixin<Intf1>
和Magic<Mixin, Intf2>
是Intf2
。
目前,我正在使用单独的 trait 来检查基类中的方法是否可用,但是这种解决方案存在一些问题:
- 我必须重申函数签名。
- 我不确定该方法是否是虚拟的(尽管看起来,这是可以做到的)。
- 由于类型转换/常量,我可能会尝试覆盖与我的方法签名不完全匹配的方法。
我希望可能有更好的解决方案。如果 myMixin
是导致替换失败的课程,我会尝试这样的事情:Godbolt。
解决方案
无法检测函数是否为虚函数。
但如果 的所有纯虚函数都T
被 覆盖Mixin
,它可以工作:
#include <type_traits>
struct Intf1{
virtual void f() = 0;
};
struct Intf2 {};
struct Intf3{
virtual void f2() = 0;
};
template <class T>
struct Mixin : public T{
virtual void f() {}; // don't mark 'override', it will break SFINAE.
};
template<template<typename>class MixIn, typename T, typename = void>
struct Applier{
typedef T type;
};
template<template<typename>class MixIn, typename T>
struct Applier<MixIn, T, typename std::enable_if<std::is_abstract<T>::value && std::is_abstract<MixIn<T>>::value>::type>{
typedef T type;
};
template<template<typename>class MixIn, typename T>
struct Applier<MixIn, T, typename std::enable_if<std::is_abstract<T>::value && !std::is_abstract<MixIn<T>>::value>::type>{
typedef MixIn<T> type;
};
template<template<typename>class MixIn, typename T>
using applier_t = typename Applier<MixIn, T>::type;
static_assert(std::is_same<applier_t<Mixin, Intf1>, Mixin<Intf1>>::value, "overridden");
static_assert(std::is_same<applier_t<Mixin, Intf2>, Intf2>::value, "not abstract");
static_assert(std::is_same<applier_t<Mixin, Intf3>, Intf3>::value, "not overridden");
推荐阅读
- phpstorm - PHP 语言级别缺少最新(版本 7.3 是最高的)
- c - 如何在 C 中创建模块
- java - fusedLocationProvider 在主线程上运行,即使方法是从不同的可运行线程调用的
- reactjs - Code not working after redux function in axios call
- ios - 如何在不打开父应用程序的情况下使用 SwiftUI for Widget 添加点击事件和更新视图?
- python - 如何使用 Pyspark 根据条件从另一个表更新表的 Spark DataFrame 列值
- android - 谷歌应用操作审核流程的时间长度是多少?
- http - 上传视频的大小在服务器上为 0,即使视频有大小
- laravel - 是否有任何使用 Office 365 邮件发送邮件的 Laravel 软件包?
- javascript - 我应该使用什么来根据过滤器选择获取更新的计数?