首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >模板接受所有成员函数指针(包括CV-合格和参考-合格)

模板接受所有成员函数指针(包括CV-合格和参考-合格)
EN

Stack Overflow用户
提问于 2021-08-05 12:56:39
回答 1查看 95关注 0票数 3

我想要编写一个模板,它接受指向成员函数的指针(可能是CV限定的和/或ref限定的),同时也匹配所有相关类型(返回值的类型、类类型和参数的类型)。

简单的版本如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <typename ReturnValue, typename Class, typename... Arguments>
void foo(ReturnValue(Class::* function_ptr)(Arguments...))
{
    // do something with |function_ptr|
}

这可以很好地适用于非CV合格的非推荐成员函数指针,但不能与指向CV合格和/或ref限定成员函数的指针匹配。

是否有一种很好的方法将其保存在一个模板中,并以某种方式通过很好地演绎限定符来处理所有情况?

我可以降级为一个简单的模板,接受一切(可能与一些SFINAE围绕std::is_member_function_pointer)。但是我仍然需要在某个地方提取类型(返回、类和参数),这样实际上不会为我节省任何工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-05 13:46:21

如何将成员函数指针传递到foo,并使用帮助器特性检索类的类型、返回和参数!

提供如下特征:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename Class> struct class_traits final {};
template<typename ReType, typename Class, typename... Args>
struct class_traits<ReType(Class::*)(Args...)> final
{
    using class_type = Class;
    using ret_type = ReType;
};    

// traits helpers
template<typename MemFunctionPtr> using  class_type = typename class_traits<MemFunctionPtr>::class_type;
template<typename MemFunctionPtr> using  ret_type = typename class_traits<MemFunctionPtr>::ret_type;

现在在foo

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <functional> // std::invoke

template <typename MemFuncType, typename... Args>
void foo(MemFuncType&& func, Args&&... args) 
{
    // class type can be retrieved!
    class_type<MemFuncType> obj{};

    // types other than void!!
    ret_type<MemFuncType> res = std::invoke(func, obj, std::forward<Args>(args)...); 

    // do something with |function_ptr|

}

现在是故事的主要部分。以上仅解析成员函数指针的非const、非volatile和非noexcept等版本。你刚才问的东西不见了!

剩下的,我们需要提供不同的特征。从这个职位的灵感出发,我们可以通过宏来完成它,这将为我们完成这些特征的样板复制:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename Class> struct class_traits final {};
#define CREATE_CLASS_TRAITS(...) \
template<typename ReType, typename Class, typename... Args> \
struct class_traits<ReType(Class::*)(Args...)__VA_ARGS__> final  \
{ \
    using class_type = Class; \
    using ret_type = ReType; \
}

CREATE_CLASS_TRAITS();
CREATE_CLASS_TRAITS(const);
CREATE_CLASS_TRAITS(volatile);
CREATE_CLASS_TRAITS(const volatile);
CREATE_CLASS_TRAITS(&);
CREATE_CLASS_TRAITS(const&);
CREATE_CLASS_TRAITS(volatile&);
CREATE_CLASS_TRAITS(const volatile&);
CREATE_CLASS_TRAITS(&&);
CREATE_CLASS_TRAITS(const&&);
CREATE_CLASS_TRAITS(volatile&&);
CREATE_CLASS_TRAITS(const volatile&&);
CREATE_CLASS_TRAITS(noexcept);
CREATE_CLASS_TRAITS(const noexcept);
CREATE_CLASS_TRAITS(volatile noexcept);
CREATE_CLASS_TRAITS(const volatile noexcept);
CREATE_CLASS_TRAITS(&noexcept);
CREATE_CLASS_TRAITS(const& noexcept);
CREATE_CLASS_TRAITS(volatile& noexcept);
CREATE_CLASS_TRAITS(const volatile& noexcept);
CREATE_CLASS_TRAITS(&& noexcept);
CREATE_CLASS_TRAITS(const&& noexcept);
CREATE_CLASS_TRAITS(volatile&& noexcept);
CREATE_CLASS_TRAITS(const volatile&& noexcept);
#undef CREATE_CLASS_TRAITS

// traits helpers
template<typename MemFunctionPtr> using  class_type = typename class_traits<MemFunctionPtr>::class_type;
template<typename MemFunctionPtr> using  ret_type = typename class_traits<MemFunctionPtr>::ret_type;

现在我们可以:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <typename MemFuncType, typename... Args>
void foo(MemFuncType&& func, Args&&... args) 
{
    class_type<MemFuncType> obj{};

    using Type = decltype(std::invoke(func, obj, std::forward<Args>(args)...));
    static_assert(std::is_same_v<ret_type<MemFuncType>, Type>, "are not same");

    std::invoke(func, obj, std::forward<Args>(args)...);

    // do something with |function_ptr|
}

class MyClass
{
public:
    void func() { std::cout << "MyClass::void func()\n"; }
    void func1() const { std::cout << "MyClass::void func1() const\n"; }
    void func2() const noexcept{ std::cout << "MyClass::void func2() const noexcept\n"; }
    int func3() const { std::cout << "MyClass::func3() const\n";  return {}; }
    int func4(int a, double b) const { std::cout << "MyClass::func3() const"<< a << " " << b << "\n";  return {}; }
};

int main()
{
    foo(&MyClass::func);
    foo(&MyClass::func1);
    foo(&MyClass::func2);
    foo(&MyClass::func3);
    foo(&MyClass::func4, 1, 2.);
    return 0;
}

(参见在线直播演示)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68673408

复制
相关文章
撰写合格的REST API
两周前因为公司一次裁人,好几个人的活都被按在了我头上,这其中的一大部分是一系列REST API,撰写者号称基本完成,我测试了一下,发现尽管从功能的角度来说,这些API实现了spec的显式要求,但是从实际使用的角度,欠缺的东西太多(各种各样的隐式需求)。REST API是一个系统的backend和frontend(或者3rd party)打交道的通道,承前启后,有很多很多隐式需求,比如调用接口与RFC保持一致,API的内在和外在的安全性等等,并非提供几个endpoint,返回相应的json数据那么简单。仔细研
tyrchen
2018/03/28
1.6K0
撰写合格的REST API
密码验证合格程序(算法)
/** * 021Abc9Abc1 * 1.长度超过8位 * 2.包括大小写字母.数字.其它符号,以上四种至少三种 * 3.不能有长度大于2的包含公共元素的子串重复 (注:其他符号不含空格或换行) */ public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
用户9919783
2022/12/14
1.1K0
重构:撰写合格的代码
在「代码重构之道」里,我犯了个懒,讨论了什么情况下需要考虑重构,以及工具和方法来促进重构,但对如何重构代码本身,或者说:如何把烂代码转化成好代码,或者至少是合格的代码,没有太多提及。这篇文章谈一谈这个话题。 我们先给「合格的代码」做个定义: 满足项目所定义的 lint 规则 代码清晰简洁,没有反人类的逻辑或者刻意为之的 trick 尽可能控制副作用 代码的注释适量,不多不少 代码的接口定义合理,很难误用或者滥用 第一条不消说,我们在前文中已经描述了一个严格限制的 lint 规则,lint 规则并非普适,每个
tyrchen
2018/03/28
1K0
重构:撰写合格的代码
怎样制作衬衣合格证
工厂在生产产品的时候,最后通过检验,合格的产品都会有一个合格证,这种合格证在日常生活和工作中随处可见,比如服装、纺织、鞋帽、电器、箱包、家电等行业都有应用。合格证就是表明出厂的产品经质量检验是合格的,也是生产者对其产品质量作出的保证。下面我们以服装行业为例子,做一个衬衣合格证。
神奇像素科技
2022/01/06
6640
怎样制作衬衣合格证
如何制作产品合格证
在日常生活中,产品合格证随处可见。我们购买的产品上都贴有吊牌及合格证。产品合格证是指生产者为表明出厂的产品经质量检验合格,附于产品或者产品包装上的合格证书、合格标签或者合格印章等。这是生产者对其产品质量作出的明示保证,也是法律规定生产者所承担的一项产品标识义务。产品合格证上一般包含产品名称、产品型号、规格、执行标准、出厂日期、检验员等,下面我们就详细介绍如何制作产品合格标签。
神奇像素科技
2021/12/14
8910
如何制作产品合格证
VC和GCC成员函数指针实现的研究(三)
因为是兼容虚继承和非虚继承的,所以赋值的部分的汇编是一样的。这里就不贴了。关键在于执行期它是怎么找到虚基类的。请往下看:
owent
2018/08/01
8240
VC和GCC成员函数指针实现的研究(三)
VC和GCC成员函数指针实现的研究(二)
调用的时候主要看(c.*vptr2)()的代码。因为(c.vptr1)()生成的和单继承一样。而由于它们最终都转向vcall,所以vptr2的时候调整了虚表指针为c的第二个虚表。顺便把this指针地址调整了。
owent
2018/08/01
6990
VC和GCC成员函数指针实现的研究(二)
WordPress常用模板函数参考文档
基本模板文件 文件名 描述 style.css 主题样式文件 index.php 首页模板文件 header.php 头部模板文件 single.php 单篇文章模板文件 archive.php 存档/分类模板文件 searchform.php 搜索表单模板文件 search.php 搜索模板文件 404.php 404模板文件 comments.php 留言模板文件 footer.php 底部模板文件 sidebar.php 侧边栏模板文件 page.php 静态页面模板文件 f
玖柒的小窝
2021/10/22
5320
C++ 类模板中成员函数和普通函数创建时机
类模板中成员函数和普通函数创建时机是有区别的: 普通类中的成员函数一开始就创建; 类模板中的成员函数在调用时才创建。 #include<iostream> using namespace std; class Demo1{ public: static void show_demo1(){ cout<<"This is Demo1."<<endl; } }; class Demo2{ public: static void show_demo2(){
耕耘实录
2022/05/09
1.2K0
过滤不合格细胞和基因(数据质控很重要)
现在一起看看拿到表达矩阵后有一个很重要的质控过程,就是根据一些阈值来过滤不合格细胞和基因。、细胞的不合格很容易理解, 可能是那个细胞检测到的基因数量太少,或者太多,也许是那个细胞的文库大小异常,都是需要谨慎考虑是否管理它。
生信技能树jimmy
2020/03/30
2.5K0
如何成为合格的架构师
一直以来,在软件行业,对于什么是架构,都有很多的争论,每个人都有自己的理解。甚至于很多架构师一说架构,就开始谈论什么应用架构、硬件架构、数据架构等等。我曾经也到处寻找过架构的定义,请教过很多人,结果发现,没有大家都认可的定义。套用一句关于 big data 流行的笑话,放在架构上也适用:
leon公众号精选
2022/04/27
2650
如何成为合格的架构师
做一名合格的DBA
Oracle DBA的角色定义 开发型DBA 数据库安装 数据库架构设计(架构和建模) 代码开发(存储过程,SQL) 运维型DBA 数据库日常监控 故障处理 性能优化 数据备份,容灾 数据库安全规划 DBA的操守 在自己的责任范围内 让数据库设计更合理,预防设计导致的性能或安全隐患 数据更安全 数据库性能更优 数据库日常管理更合理 故障发现,处理及时 数据库的架构设计 数据库架构 分布or单库 实例的冗余 RAC or single 数据库的安全和容灾 DG or streams or Rman 空间的考虑
职场亮哥
2020/10/10
4150
VC和GCC内成员函数指针实现的研究(一)
最近在《C++对象模型》一书里说到的virtual的成员函数指针,低于128的被cfront编译器认为是虚表偏移量(支持子类对父类函数的覆盖)。VC只是提了下单继承、多继承和虚继承的实现方案不同,GCC没有提及,所以就专门稍微深入分析研究下他们的实现机制。
owent
2018/08/01
8520
VC和GCC内成员函数指针实现的研究(一)
VC和GCC内成员函数指针实现的研究(一)
最近在《C++对象模型》一书里说到的virtual的成员函数指针,低于128的被cfront编译器认为是虚表偏移量(支持子类对父类函数的覆盖)。VC只是提了下单继承、多继承和虚继承的实现方案不同,GCC没有提及,所以就专门稍微深入分析研究下他们的实现机制。
owent
2023/03/17
5470
VC和GCC内成员函数指针实现的研究(一)
ChatGPT当面试官觉得合格吗?
用户2242639
2023/02/28
4250
ChatGPT当面试官觉得合格吗?
函数指针和指针函数用法和区别
函数指针和指针函数,在学习 C 语言的时候遇到这两个东西简直头疼,当然还有更头疼的,比如什么函数指针函数、指针函数指针、数组指针、指针数组、函数指针数组等等,描述越长其定义就越复杂,当然理解起来就越难,特别是刚开始学习这门语言的童鞋,估计碰到这些东西就已经要崩溃了,然后好不容易死记硬背下来应付考试或者面试,然后过了几天发现,又是根本不会用,也不知道该在哪些地方用,这就尴尬了。 今天这里只讲两个相对简单的,其实上面说那些太复杂的东西也真的很少用,即便是用了理解起来很麻烦,所以莫不如先深刻理解这两个比较容易的,并且项目中比较常用到。
全栈程序员站长
2022/06/25
2250
c++之空指针访问成员函数
#include<iostream> using namespace std; class Person { public: int age; void showClass() { cout << "这是Person类" << endl; } void showAge() { //解决方法,如果是空就直接返回 if (this == NULL) { return; } co
西西嘛呦
2020/08/26
6190
合格的后端Coder都应该写好UT和Mock测试
作者 | S.L 来源 | http://r6d.cn/aaTem 关于测试 1 测试都包括哪些 广义的测试包括 UT、IT、压力测试、硬件测试等等,这里重点讨论 Unit Test 即单元测试。 2 啥是 UT 单元测试(又称为模块测试, Unit Testing)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。 简
程序猿DD
2023/04/04
7210
合格的后端Coder都应该写好UT和Mock测试
UiPath做RPA行业的“灯塔”,合格么?
RPA,机器流程自动化,近两年开始热起来了。在资本市场,开始有不少大手笔的投资案例。春江水暖鸭先知,资本是科技行业的风向标。很多行业都是资本先行,在资本推动下,一个个细分领域在短时间内被推向舞台中央。火候到了的就顺风顺水,从此开启暴走模式;如果资本看走眼,该行业还没到火候,在短暂的狂欢之后就剩一地鸡毛。
数据猿
2022/03/16
6600
UiPath做RPA行业的“灯塔”,合格么?
点击加载更多

相似问题

参考合格成员函数

14

简历合格类型不能转换为cv-不合格类型。

11

合格的类成员

10

简历-合格数据成员和铸件

13

简历-合格参考资料

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文