2411C++,默认参数为调用者指针

server/2024/11/24 8:50:01/

原文
前段时间,研究了按调用者指针设置方法默认参数.场景如下:

struct Property
{Property(char const* name, int initial, Object* owner) :m_name(name), m_value(initial), m_owner(owner) {}//省略其他方法char const* m_name;Object* m_owner;int m_value;
};
struct Widget : Object
{Property Height{ "Height", 10, this };Property Width{ "Width", 10, this };
};

不想对所有属性构造器的最后参数输入.想出了如下:

template<typename D>
struct PropertyHelper
{Property Prop(char const* name, int initial){ return Property(name, initial, static_cast<D*>(this)); }
};
struct Widget : Object, PropertyHelper<Widget>
{Property Height = Prop("Height", 10);Property Width = Prop("Width", 10);
};

或,如果你知道推导本,

struct PropertyHelper
{template<typename Parent>Property Prop(this Parent&& parent, char const* name, int initial){ return Property(name, initial, &parent); }
};
struct Widget : Object, PropertyHelper
{Property Height = Prop("Height", 10);Property Width = Prop("Width", 10);
};

但这使用了一个固定的参数列表.如果必须处理多种属性怎么办?

template<typename T>//..
struct Property
{Property(char const* name, T const& initial, Object* owner) ://..m_name(name), m_value(initial), m_owner(owner) {}//省略其他方法char const* m_name;Object* m_owner;T m_value;//..
};

任意类型,而不仅是属性的特化?

template<typename Handler>
struct Event
{Event(char const* name, Object* owner) :m_name(name), m_owner(owner) {}//省略其他方法char const* m_name;Object* m_owner;std::vector<Handler> m_handlers;
};

所有这些小类共同点是它们按最终参数,带包含类的指针.是否可不必创建一堆对应需要包装的每种类型的一次的类,就泛化该方法?

可以!想法是使用刚才看到的一个技巧:你可根据调用者的需求,通过返回一个保留参数代理类型,模拟一个返回不同类型函数,然后在通过转换符号显示目标类型干活.

template<typename...Args>
struct maker
{std::tuple<Args&&...> m_args;maker(Args&&... args) : m_args((Args&&)args...) {}template<typename T>operator T() {return std::make_from_tuple<T>(std::move(m_args));}
};
template<typename D>
struct OwnerHelper
{template<typename...Args>auto Owned(Args&&... args){ return maker<Args&&..., D*>((Args&&)args..., static_cast<D*>(this)); }
};
struct Widget : Object, OwnerHelper<Widget>
{Property<int> Height = Owned("Height", 10);Property<std::string> Name = Owned("Name", ""s);Event<NameChangedHandler> NameChanged = Owned("NameChanged");
};

这里很微妙:需要转换参数以确保保留其引用分类.
注意,使用参数包,表明必须编写类似""sstd::string{}的东西而不是更方便的{},来获得空串,因为模板类型参数匹配类型,而不是可用来构建不是自身类型的类型的支撑内容.

如前,可通过推导 本简化它:

struct OwnerHelper
{template<typename O, typename...Args>auto Owned(this O&& self, Args&&... args)//..{return maker<Args&&..., O*>((Args&&)args..., &self);//..}
};
struct Widget : Object, OwnerHelper
{Property<int> Height = Owned("Height", 10);Property<std::string> Name = Owned("Name", ""s);Event<NameChangedHandler> NameChanged = Owned("NameChanged");
};

http://www.ppmy.cn/server/144492.html

相关文章

营销的本质

最近很多人问我营销到底是什么&#xff1f;发现很多人对营销的概念不清晰&#xff0c;受网络上碎片化知识的影响&#xff0c;把销售的过程当成营销全流程对待。从企业经营的角度&#xff0c;营是上位概念&#xff0c;销是下位概念。一、战略与战术 在营销体系设置中&#xff0c…

应急响应靶机——linux2

载入虚拟机&#xff0c;打开虚拟机&#xff1a; 居然是没有图形化界面的那种linux&#xff0c;账户密码&#xff1a;root/Inch957821.&#xff08;注意是大写的i还有英文字符的.&#xff09; 查看虚拟机IP&#xff0c;192.168.230.10是NAT模式下自动分配的 看起来不是特别舒服&…

Java基础面试题03:简述什么是迭代器(Iterator)?

面试题&#xff1a;简述什么是迭代器(Iterator)&#xff1f; 一、什么是Iterator&#xff1f; 迭代器&#xff08;Iterator&#xff09;是一个专门用来遍历集合&#xff08;如数组、列表等&#xff09;中的元素的对象。它可以帮助开发者按照一定的规则顺序访问集合中的每一个…

商业物联网:拥抱生产力的未来

在现代商业格局中&#xff0c;数据占据至高无上的地位。物联网&#xff08;IoT&#xff09;站在这场数字革命的前沿&#xff0c;将以往模糊不清的不确定因素转变为可衡量、可付诸行动的深刻见解。物联网技术为日常物品配备传感器与连接功能&#xff0c;使其能够实时收集并传输数…

Ubuntu下的Graphviz的基础使用方法

一、Graphviz介绍 graphviz是贝尔实验室开发的一个开源的工具包&#xff0c;它使用一个特定的DSL(领域特定语言):dot作为脚本语言&#xff0c;然后使用布局引擎来解析此脚本&#xff0c;并完成自动布局 1、什么是Graphviz 官网地址&#xff0c;https://www.graphviz.org/ Gr…

MySQL执行计划

环境 MySQL版本8.3.0 数据准备 新建一个explain_test的数据库&#xff0c;包含三张表&#xff1a;演员表、影片表、影片与演员关联表。 表结构如下所示&#xff1a; 什么是执行计划 根据MySQL的执行计划信息&#xff0c;可以用来分析当前查询的执行过程&#xff0c;是否用到…

活着就好20241124

今天是周日&#xff0c;一个同样洋溢着休闲与宁静气息的日子。亲爱的朋友们&#xff0c;大家早上好&#xff01;在经历了一周的忙碌之后&#xff0c;我们终于迎来了这个让人期待已久的休息日。周日&#xff0c;不仅是一个放松身心的绝佳时机&#xff0c;更是我们回归自我、享受…

【Java】期末复习章节 未完待续(版)

文章目录 【01算法类】1.1 使用冒泡排序算法对数组a{9, 7, 4, 6, 3, 1,10}&#xff0c;按由小到大的规律排序数组中的元素。1.2 从键盘输入一个4位整数n&#xff0c;判断n是否是回文数。&#xff08;回文数是指&#xff0c;将其数字反转排列的数与其本身相同。例如&#xff1a;…