实现抽象类作为其他类的接口,无需 vtable 开销

2024-01-06

我想做接口类ForwardIterator, BiderctionalIterator and RandomAccessIterator,每一个都有一些操作符(它们都是纯虚拟的,没有实现)。现在,如果我想为容器实现迭代器,我只需从正确的迭代器继承,并在我不小心忘记实现某些函数/运算符时获得编译器的帮助。 使用纯虚函数来实现它效果很好,但是它有 vtable 的开销,这是不必要的,因为所有代码需求都可以在编译时定义。

template <typename T>
struct ForwardIterator{
    virtual T operator++() = 0;
    virtual T operator++(int) = 0;
};

template <typename T>
struct BidirectionalIterator: public ForwardIterator<T>{
    virtual T operator--() = 0;
    virtual T operator--(int) = 0;
};

template <typename T>
struct RandomAccessIterator: public Bidirectional<T>{
    virtual T operator+(int) = 0;
    virtual T operator-(int) = 0;
};

// Custom Iterator Implementation

class MyCustomRandomAccessIterator
   : public RandomAccessIterator<MyCustomRandomAccessIterator>{
    // get errors if I miss some function definitions.
    // but it has vtable !!!

};

如果我理解正确的话,您需要确保某些方法在最终的派生类中实现,但不使用经典方式(抽象继承),因为它太重了。

我的第一个想法是简单地声明而不是定义方法

template <typename T>
struct ForwardIterator {
    T operator++ ();
    T operator++ (int);
};

所以当你使用这些方法时

MyCustomRandomAccessIterator  i;

++i;

你会得到一个链接器错误。

但是,只有当您使用忘记的方法时,您才会收到链接器错误(我想您更喜欢编译错误),因此,如果您忘记了单个方法,则可能很难检测到它(您需要将其与对象一起使用)。

所以我的想法,也许并不完美,是delete方法,添加构造函数并检查最终类中方法是否存在。

我的意思是...就像

template <typename T>
struct ForwardIterator {
    T operator++ () = delete;
    T operator++ (int) = delete;

    ForwardIterator ()
     {
       static_assert( sizeof(decltype(std::declval<T>()++)), "!" );
       static_assert( sizeof(decltype(++std::declval<T>())), "!" );
     }
};

这样你就可以获得所有编译错误(如果你愿意的话,也许,带有有意义的错误消息,比"!")简单地声明你的类的一个对象

MyCustomRandomAccessIterator  i;

// ++i; // no needs of invoke the forgotten methods to get the errors

以下是完整的编译示例

#include <utility>

template <typename T>
struct ForwardIterator {
    T operator++ () = delete;
    T operator++ (int) = delete;

    ForwardIterator ()
     {
       static_assert( sizeof(decltype(std::declval<T>()++)), "!" );
       static_assert( sizeof(decltype(++std::declval<T>())), "!" );
     }
};

template <typename T>
struct BidirectionalIterator: public ForwardIterator<T> {
    T operator-- () = delete;
    T operator-- (int) = delete;

    BidirectionalIterator ()
     {
       static_assert( sizeof(decltype(std::declval<T>()--)), "!" );
       static_assert( sizeof(decltype(--std::declval<T>())), "!" );
     }
};

template <typename T>
struct RandomAccessIterator: public BidirectionalIterator<T>{
    T operator+ (int) = delete;
    T operator- (int) = delete;

    RandomAccessIterator ()
     {
       static_assert( sizeof(decltype(std::declval<T>()+0)), "!" );
       static_assert( sizeof(decltype(std::declval<T>()-0)), "!" );
     }
 };

// Custom Iterator Implementation

struct MyCustomRandomAccessIterator
   : public RandomAccessIterator<MyCustomRandomAccessIterator> {

   // with `if 0` (forgetting definition of requested methods) you get
   // a lot of compilation errors   
#if 1
    MyCustomRandomAccessIterator operator++ ()
     { return *this; } 

    MyCustomRandomAccessIterator operator++ (int)
     { return *this; } 

    MyCustomRandomAccessIterator operator-- ()
     { return *this; } 

    MyCustomRandomAccessIterator operator-- (int)
     { return *this; } 

    MyCustomRandomAccessIterator operator+ (int)
     { return *this; } 

    MyCustomRandomAccessIterator operator- (int)
     { return *this; } 
#endif
};

int main()
 {
   // simply declaring i you get a lot of errors, in case of no 
   // methods definitions
   MyCustomRandomAccessIterator  i;
 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现抽象类作为其他类的接口,无需 vtable 开销 的相关文章

  • 如何使用 C# 打印 pdf

    我在 C 应用程序中使用 进程 打印 pdf 文件 但是我无法获取打印状态 我发现可以通过 System management 和 System printing 与打印机 队列进行交互 我做了很多尝试 但都出错了使用这两个命名空间但无法打
  • 在两个 .cpp 文件之间定义全局变量 [重复]

    这个问题在这里已经有答案了 如何在 A cpp 和 B cpp 之间共享 全球化 bool 变量 其中它们都不包含其他 h 文件 他们有其他联合头文件 但彼此没有 我可以在这些共享标头中定义全局变量吗 Thanks 我可以在这些共享标头中定
  • 何时对向量进行归一化?

    我正在学习 XNA 并且在几乎所有的教育套件中都可以找到http creators xna com en US http creators xna com en US 我总是看到向量上对 Normalize 的调用 我知道归一化基本上将向量
  • 如何将 C++ 类包装在基于 C 的 dll 或基于 CLI 的 dll 中?

    我被告知将我用 C 编写的类导入到 dll 中 然后在 c 应用程序中使用该 dll 下列的本指南 https stackoverflow com questions 4555961 how to use a class in dll我创建
  • C++ - 模板专业化和部分专业化

    我一直在互联网和 stackoverflow 上寻找具体的答案 但我似乎找不到 我必须创建一个通用类 然后实现特定的功能 我的具体说明是 您需要使用模板表达式参数以及模板类专业化和部分专业化 我有一个模板类 template
  • WPF - 按多列排序时使用自定义比较器

    我有一个 ListView GridView 我想按 2 列排序 因此如果第 1 列中有 2 个以上的项目具有相同的值 它将按第 2 列排序 非常简单 但是在对 A Z 进行排序时 空字符串会出现在顶部 我想把它们移到底部 我制作了一个比较
  • 使用 QSet 作为 Qt 地图容器中的键

    我需要一个映射 其中键是唯一的 并且每个键都是一组或自定义 POD 结构 其中包含 3 个数据项 这些值只是指向对象实例的指针 从阅读Qt 的 QMap 与 QHash 的文档 http qt project org doc qt 4 8
  • 将语句插入 SQL Server 数据库

    最近几天我试图找到这个错误 但没有成功 我正在尝试在数据库中插入一个新行 一切都很顺利 没有错误 也没有程序崩溃 My INSERT声明如下 INSERT INTO Polozaj Znesek Uporabnik Cas Kupec Po
  • 我们应该使用 Eval 还是 Databind 事件?

    当使用 Asp Net 并使用 ListView 等控件创建网站时 使用 Eval 命令是一个好习惯吗 还是应该在 databind 事件中填充文字和数据 取决于您是否想在更新事件上写回数据 在这种情况下数据绑定 如果您只想读取该数据 可以
  • IClaimsTransformation 未触发

    我尝试过实施一个IClaimsTransformation我在 ASP NET CORE 3 1 Web 应用程序中找到的类 public class ClaimsTransformer IClaimsTransformation publ
  • 从 ef core 的子集合中删除一些项目

    我有一个父表和子表 其中父表与子表具有一对多关系 我想删除一些子项 并且希望父项的子集合反映该更改 如果我使用删除选定的子项RemoveRange 那么子集合不会更新 如果我使用Remove从子集合中删除子集合然后 显然 它不如使用效率高R
  • 在 C# 中生成随机值

    如何使用以下命令生成随机 Int64 和 UInt64 值RandomC 中的类 这应该可以解决问题 这是一个扩展方法 因此您可以像调用普通方法一样调用它Next or NextDouble上的方法Random目的 public stati
  • 打破条件变量死锁

    我遇到这样的情况 线程 1 正在等待条件变量 A 该变量应该由线程 2 唤醒 现在线程 2 正在等待条件变量 B 该变量应该由线程 1 唤醒 在我使用的场景中条件变量 我无法避免这样的死锁情况 我检测到循环 死锁 并终止死锁参与者的线程之一
  • IEnumerable.比带中断的 for 循环更快吗?

    我们的代码打开表单时遇到了一些缓慢的情况 这可能是由于for循环与break这需要很长时间才能执行 我把它切换到IEnumerable Any 并看到表格很快打开 我现在试图弄清楚是否单独进行此更改会提高性能 或者是否正在访问Product
  • 如果数组为空,LINQ 返回 null

    public class Stuff public int x other stuff 我有一个IEnumerable
  • 为什么从绑定返回的对象会忽略额外的参数?

    假设我有一个带有两个参数的函数 void f int x int y 我想绑定其中之一 我可以用std bind如下 auto partiallyBoundF std bind f 10 1 partiallyBoundF仅需要一个参数 但
  • 统一;随机物体移动[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在制作一款机器人战斗游戏 我希望敌人随机移动 然后有时会向敌人移动 我希望运动包含在其中的代码 else if avoid fal
  • 计算两个日期之间的工作日数?

    在C 中 如何计算business 或工作日 两个日期之间的天数 我以前曾经遇到过这样的任务 并且我已经找到了解决方案 当可以避免的时候 我会避免列举其间的所有日子 这里就是这种情况 正如我在上面的一个答案中看到的那样 我什至没有提到创建一
  • C# 中成员访问中的问号是什么意思?

    有人可以向我解释一下以下代码中会员访问中的问号是什么意思吗 它是标准 C 的一部分吗 尝试在 Xamarin Studio 中编译此文件时出现解析错误 this AnalyzerLoadFailed Invoke this new Anal
  • 如何获取通过网络驱动器访问的文件的 UNC 路径?

    我正在 VC 中开发一个应用程序 其中网络驱动器用于访问文件 驱动器由用户手动分配 然后在应用程序中选择驱动器 这会导致驱动器并不总是映射到相同的服务器 我该如何获取此类文件的 UNC 路径 这主要是为了识别目的 这是我用来将普通路径转换为

随机推荐

  • 我可以使用 perl 创建数据透视表吗?

    我使用 Excel Writer XLSX 模块使用 Perl 生成 Excel 文件 我把数据放在一张纸上 我想在创建 Excel 文件时自动创建包含该数据的数据透视表和图表 数据透视表和图表需要有过滤器 所以我可以选择月 周 状态 部门
  • Kafka主题未被删除

    我使用的是卡夫卡 0 10 0 1 集群中有 3 个代理 我发出了删除命令 删除了近 10 个一个月以来没有使用过的主题 我检查过 没有消费者注册这些主题 他们的日志大小也没有增加 然而 已经过去5个多小时了 那些话题还没有被删除 它们只是
  • 为什么使用迭代器而不是数组索引?

    采取以下两行代码 for int i 0 i lt some vector size i do stuff 和这个 for some iterator some vector begin some iterator some vector
  • PHP 的 T_VAR 错误

    我正在开发一个 html 表单 它将数据发送到一个显示它的 php 文件 最终我会让 php 将数据发送到 mysql 数据库 当我提交表单时 出现 php 错误 解析错误 语法错误 第 2 行 home2 rocksoli public
  • 如何从测试导航器中删除 Xcode Swift 测试类?

    Xcode 测试导航器显示测试用例类的列表 我想删除一个测试用例类 因为不再需要它 我尝试过许多典型的方法 例如按删除键 或查找 图标 或 删除 菜单项 或在 Apple Xcode 文档中搜索帮助 我找到了这个解决方法 在项目导航器中 从
  • Facebook API 营销:创建自定义受众的问题

    我尝试通过 APPUID 将用户添加到自定义受众 我确实发布到网址https graph facebook com v2 10 CUSTOM AUDIENCE ID users https graph facebook com v2 10
  • Emacs 日历:显示超过 3 个月?

    在 Emacs 中 当您使用以下命令显示日历时M x calendar 您可以在一个只有 8 行高的新窗口中显示三个月的信息 上个月 本月和下个月 是否可以在全尺寸窗口中生成十二个月的日历 12 个月日历 按月滚动 向前 向后 Scroll
  • 检测由于违反唯一约束而导致的 mysql 更新/插入失败

    这有点类似于这个问题 PHP MySQL INSERT 由于唯一约束而失败 https stackoverflow com questions 2756186 php mysql insert fails due to unique con
  • 如何从 MS SQL 数据表中检索列默认值

    我在用DataAdapter FillSchema从 MS SQL 检索表的架构 不幸的是 这不会返回列的默认值 当我需要检查数百个表时 有没有一种方法可以快速有效地检索此值作为架构的一部分 Thanks 默认值仅在行插入时确定 作为替代方
  • 如果 WPF 应用程序强制关闭或崩溃,处理 WPF 关闭事件

    我有一台名为 GameServer 的服务器 它持续运行 并且多个 ClientApplication 正在不同的不同机器上运行 当用户登录到服务器时 我将根据登录用户将一些数据保存到服务器 注销后我将对数据库以及我为登录用户对服务器所做的
  • 使用 Python 格式化 APNS 样式的 JSON 消息以与 Amazon SNS 一起使用

    我正在创建一个 iOS 应用程序 对于您的推送通知 我们使用 Amazon Simple Notification Service SNS SNS 很棒 但文档却相当稀疏 我在用着boto http docs pythonboto org
  • 使用“type”关键字和路径相关类型覆盖类型

    假设我有这样的代码 trait Holder type Value def put v Value class JsonHolder extends Holder override type Value String def put v J
  • Laravel Eloquent - 关系上的firstOrCreate()

    当我尝试firstOrCreate 在另一个模型的关系上 它不起作用 Client find id gt users gt firstOrCreate array email gt email 这会返回一个错误说 调用未定义的方法 Illu
  • 如何在我的 Grails 应用程序中使用 servlet?

    我需要使用一些实际上是 servlet 的连接器 我怎样才能在 Grails 中做到这一点以及 web xml 呢 如何配置 servlet 的 url 我实际上这里有一个 Spring 应用程序 我正在尝试将其转换为部分 Grails 应
  • CircularImageView 和 API 16:NullPointerException 错误

    我正在不同的 API 上测试我的应用程序 它似乎可以在 API 17 到 23 上工作 但我发现在 API 16 中 我无法加载我的自定义视图 我只想在一个圆圈中显示一张照片 并且我已经从此线程中获得了自定义视图的代码 如何在Android
  • 如何检查自动增长最后完成的时间?

    在sql server 2005中 自动增长是按大小启用的 有什么方法可以检查数据和日志文件的自动增长最后发生的时间吗 SSMS 右键单击您的数据库 转到报告 gt 标准报告 gt 磁盘使用情况并查找 Autogrow Autoshrink
  • 在 IntelliJ IDEA 中运行 jar 配置

    IntelliJ IDEA 中是否有任何选项可以创建配置来运行外部 jar 就像 Eclipse 中的外部工具配置一样 IDEA 没有专用的 可执行 JAR 运行 调试配置 这听起来确实是一个不错的新功能 我建议您提出要求 http you
  • /usr/include/dirent.h 中的 DT_WHT 意味着什么?

    我正在阅读 dirent h 的源代码 有一个枚举 enum DT UNKNOWN 0 unknown type define DT UNKNOWN DT UNKNOWN DT FIFO 1 a named pipe or FIFO def
  • 用于检测 C/C++ 应用程序中的错误共享的工具

    有没有什么工具可以检测并报告虚假分享 http en wikipedia org wiki False sharing对于用 C 或 C 编写的应用程序 试试警长和掠夺者 警长在https github com plasma umass s
  • 实现抽象类作为其他类的接口,无需 vtable 开销

    我想做接口类ForwardIterator BiderctionalIterator and RandomAccessIterator 每一个都有一些操作符 它们都是纯虚拟的 没有实现 现在 如果我想为容器实现迭代器 我只需从正确的迭代器继