使用 C++ 命名参数习惯用法的更好方法?

2024-02-05

我一直在为 Windows 开发一个 GUI 库(作为个人业余项目,不希望有用)。对于我的主窗口类,我设置了选项类的层次结构(使用命名参数惯用语 http://www.parashift.com/c++-faq-lite/named-parameter-idiom.html),因为某些选项是共享的,而其他选项则特定于特定类型的窗口(如对话框)。

命名参数习惯用法的工作方式是,参数类的函数必须返回它们所调用的对象。问题是,在层次结构中,每个人都必须是一个不同的类——createWindowOpts标准窗口类,createDialogOpts对话框类等。我已经通过制作所有选项类模板来解决这个问题。这是一个例子:

template <class T>
class _sharedWindowOpts: public detail::_baseCreateWindowOpts {
    public: ///////////////////////////////////////////////////////////////
    // No required parameters in this case.
    _sharedWindowOpts() { };

    typedef T optType;

    // Commonly used options
    optType& at(int x, int y) { mX=x; mY=y; return static_cast<optType&>(*this); }; // Where to put the upper-left corner of the window; if not specified, the system sets it to a default position
    optType& at(int x, int y, int width, int height) { mX=x; mY=y; mWidth=width; mHeight=height; return static_cast<optType&>(*this); }; // Sets the position and size of the window in a single call
    optType& background(HBRUSH b) { mBackground=b; return static_cast<optType&>(*this); }; // Sets the default background to this brush
    optType& background(INT_PTR b) { mBackground=HBRUSH(b+1); return static_cast<optType&>(*this); }; // Sets the default background to one of the COLOR_* colors; defaults to COLOR_WINDOW
    optType& cursor(HCURSOR c) { mCursor=c; return static_cast<optType&>(*this); }; // Sets the default mouse cursor for this window; defaults to the standard arrow
    optType& hidden() { mStyle&=~WS_VISIBLE; return static_cast<optType&>(*this); }; // Windows are visible by default
    optType& icon(HICON iconLarge, HICON iconSmall=0) { mIcon=iconLarge; mSmallIcon=iconSmall; return static_cast<optType&>(*this); }; // Specifies the icon, and optionally a small icon
    // ...Many others removed...
};

template <class T>
class _createWindowOpts: public _sharedWindowOpts<T> {
    public: ///////////////////////////////////////////////////////////////
    _createWindowOpts() { };

    // These can't be used with child windows, or aren't needed
    optType& menu(HMENU m) { mMenuOrId=m; return static_cast<optType&>(*this); }; // Gives the window a menu
    optType& owner(HWND hwnd) { mParentOrOwner=hwnd; return static_cast<optType&>(*this); }; // Sets the optional parent/owner
};

class createWindowOpts: public _createWindowOpts<createWindowOpts> {
    public: ///////////////////////////////////////////////////////////////
    createWindowOpts() { };
};

它可以工作,但正如您所看到的,它需要大量的额外工作:每个函数的返回类型的类型转换、额外的模板类等等。

我的问题是,在这种情况下是否有一种更简单的方法来实现命名参数惯用语,不需要所有额外的东西?


也许不是您想听到的,但我认为在库代码中(或多或少)对客户端隐藏的大量丑陋的类型转换和模板参数是可以的只要这是安全的and使客户的生活变得更加轻松。库代码的美妙之处不在于代码本身,而在于它使客户端能够编写的代码。以STL为例。

我还开发了一个小型 GUI 库作为个人项目,与您的愿望基本相同,其中一些代码变得非常丑陋,但最终它允许我编写漂亮的客户端代码(至少在我的(可能是变态的)眼睛)这才是重要的恕我直言。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 C++ 命名参数习惯用法的更好方法? 的相关文章

随机推荐

  • 对于 2^1024 到 2^4096 范围内的数字,最快的确定性素性测试是什么?

    我正在编写加密协议的实现 到目前为止 我一直很难找到 1024 位到 4096 位整数 308 到 1233 位数字 最快的确定性素性测试 我知道有几种选择 但我无法找到现实世界的速度比较 具体来说 对于这种大小的一般随机数 AKS 测试与
  • 如何循环遍历从 snapshot.val() 收到的数据并根据键将其推送到数组

    我想循环遍历我收到的数据snapshot val 基于用户密钥并将它们推入数组中 我尝试在 for in 循环的帮助下做到这一点 如下所示 firebase database ref interests child I would like
  • 不允许表达式作为字段默认值

    我正在努力使 app可供全班使用 首先 我得到 不允许表达式作为字段默认值 其次 在第 5 行 我得到 未识别的变量 app 我怎样才能实现我的目标 class UserController extends XController var
  • 如何将动态生成的元素绑定到 Intersection Observer?

    这是我正在使用的代码 var ob new IntersectionObserver entries gt for var entry of entries console log works document querySelectorA
  • 将 Dbcontext 配置为瞬态

    在 ASP NET Core EntityFramework Core 中 services AddDbContext 方法会将指定的上下文添加为作用域服务 据我了解 这是 Microsoft 建议的 dbcontext 生命周期管理 然而
  • 如何从 javascript 访问顺风颜色

    我正在使用 ApexCharts 并且想使用我的顺风颜色 红色 500 等 来设计我的图表 我无法使用 css 类 因此无法在 post css 上下文中使用 theme 我也无法引用默认配置 因为我已经扩展了它 我可以导入我的新配置的颜色
  • 在 Swing 中叠加多个 JSlider

    是否可以覆盖多个 JSlider 以便我可以看到两者上的 拇指 我已尝试禁用轨道的绘制并将不透明度设置为 false 但其中一个仍然隐藏另一个 基本上我想创建一个允许用户定义范围的组件 而且我真的不想编写自定义组件 因为它具有滑块的大部分属
  • requestFocus 不适用于 EditText

    花了很多时间解决这个问题 看起来很简单 但我真的很累 找不到解决办法 我有一个活动 活动有 4 个 EditText 组件 其中 2 个具有包含列表的弹出菜单 AlertDialog 下一个 禁用编辑 最后一个 是可编辑的 并且当用户点击它
  • java 枚举构造函数中是否允许使用可变参数?

    enum MyEnum A 1 2 3 4 B 1 2 C 4 5 8 8 9 private MyEnum int firstInt int otherInts do something with arguments perhaps in
  • 如何为 Google 地图指定自定义聚类标记

    我有一个带有标记和聚类的谷歌地图 我可以使用如下代码轻松更改标记图标 marker new google maps Marker position lat location data lat lng location data lng ma
  • 对象数组不可picklable

    我用 python 创建了一个类 如下所示 class myClass fields 1 2 其中 field 1 和 field 2 应该是整数 然后我创建了一个数组 其元素属于该类myClass如下 array myClass for
  • 如何为打字稿编译器配置`baseUrl`?

    我有一个使用模块构建的网站requireJS 我想开始在这个项目上使用 TypeScript 1 8 Visual Studio 2015 并尝试重写其中一个模块 目前我的模块如下所示 file ProjectFoo app dashboa
  • 旋转数组 LeetCode (189)

    问题如下 给定一个数组 将数组向右旋转 k 步 其中 k 为非负数 这是我的代码 class Solution public void rotate vector
  • NoSql 速成课程/教程 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我已经看到 NoSQL 在 SO 上出现了很多 并且我对why你会使用它 来自这里 维基百科等 这可能是由于缺乏对它是什么的具体和统一的定
  • Eclipse 在哪里存储更新站点列表?可以将其复制到另一个安装吗?

    我的 Eclipse 安装完全失败并且无法启动 因此我可能必须重新安装它 但这在升级到新的 Eclipse 版本时也相关 我不想寻找我安装的所有插件 那么 Eclipse 在哪里存储可用更新站点的列表呢 如果它不是纯文本形式 是否可以毫无问
  • Angular 2 中的嵌套模板[重复]

    这个问题在这里已经有答案了 我有一个组件
  • 在 ClosedXML 中应用多个过滤器 (SetAutoFilter)

    我通过 ClosedXML 对多个列应用过滤器 但是 仅应用最后一项 这些过滤器在单独使用时会起作用 我怎样才能应用所有这些 我在这里发现了类似的问题ClosedXML Excel 按多列中的值过滤行 https stackoverflow
  • Chrome 扩展页面 popup.html 无法调整大小

    所以我有这个 Chrome 扩展程序 可以从互联网上加载一些内容 基本上 用户单击弹出图标 然后后台页面中的一些 JavaScript 加载一些页面 从中解析图像并将其放入 popup html 页面中 问题是 popup html 没有调
  • 在 C# 中扩展枚举

    我想知道是否可以扩展 C 中的 Enum 类型来实现我的自定义 Enum GetValues type 并像 Enum GetMyCustomValues type 那样调用它 我正在尝试实现这样的事情 public static bool
  • 使用 C++ 命名参数习惯用法的更好方法?

    我一直在为 Windows 开发一个 GUI 库 作为个人业余项目 不希望有用 对于我的主窗口类 我设置了选项类的层次结构 使用命名参数惯用语 http www parashift com c faq lite named paramete