首页 > 解决方案 > 根据虚拟方法的存在,有条件地将 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

标签: c++templatesoverridingc++17mixins

解决方案


无法检测函数是否为虚函数。

但如果 的所有纯虚函数都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");

推荐阅读