远程过程调用-buttonrpc源码解析7-函数返回值

2024-04-04 00:28

本文主要是介绍远程过程调用-buttonrpc源码解析7-函数返回值,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前一篇文章讲述了服务端如何进行函数调用,但并未分析函数返回值,本节进行重点分析。
在负责拆分委托函数的callproxy_函数内,最终得到了型如
typename type_xx<R>::type r = call_helper<R>(ff, args);或者
typename type_xx<R>::type r = call_helper<R>(func, args);的调用形式。
1、函数call_helper相关的定义如下:

// 定义一个泛化的特征模板,用于确定函数返回值类型:T型的type就是T本身
template<typename T>
struct type_xx{	typedef T type; };
// 定义一个特化模板:void型的type为int8_t
template<>
struct type_xx<void>{ typedef int8_t type; };// 调用帮助类,主要用于返回是否void的情况:是,并返回0
template<typename R, typename F, typename ArgsTuple>
typename std::enable_if<std::is_same<R, void>::value, typename type_xx<R>::type >::type
call_helper(F f, ArgsTuple args) {invoke(f, args);return 0;
}
// 调用帮助类,主要用于返回是否void的情况:否,返回真正的返回值
template<typename R, typename F, typename ArgsTuple>
typename std::enable_if<!std::is_same<R, void>::value, typename type_xx<R>::type >::type
call_helper(F f, ArgsTuple args) {return invoke(f, args);
}// 具体实现函数模板:用tuple做参数调用函数模板类
template<typename Function, typename Tuple, std::size_t... Index>
decltype(auto) invoke_impl(Function&& func, Tuple&& t, std::index_sequence<Index...>)
{return func(std::get<Index>(std::forward<Tuple>(t))...);
}
// 函数模板:作为一个接口,负责调用相关函数并传递参数
template<typename Function, typename Tuple>
decltype(auto) invoke(Function&& func, Tuple&& t)
{constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;return invoke_impl(std::forward<Function>(func), std::forward<Tuple>(t), std::make_index_sequence<size>{});
}

首先定义一个特征类模板type_xx用来获得函数的返回值类型,这里void类型的返回值并非void,而是特化为int8_t类型,是因为无法定义一个void类型的变量来接call_helper的返回值。
接着定义了两个call_helper函数模板,通过使用std::enable_if来利用函数模板的重载决议SFINAE特性,为void类型和其它类型实例化不同的函数。通过decltype(auto),能够自动推导函数返回值类型。
最后定义invokeinvoke_impl两个函数模板,这两个函数模板用来执行函数的实际调用,之前的文章有讲过,这里不再赘述。
其实到这里,整个服务端函数调用的过程差不多已经分析完了,invoke函数已经能够得到正确的返回值了,而call_helper函数也已完成了它的使命,给出了对应的返回值。
温馨提示std::is_same用于比较两个类型是否一致,类型一致则value为true,否则value为false。std::enable_if用于条件编译,它通常与函数模板一起使用,以便根据某些类型特性或表达式结果来选择合适的函数重载(常出现于SFINAE场景中)。decltype(auto)主要用于推导转发函数和类似包装的返回类型。
2、函数返回值包裹类型
函数调用成功与否,都需要给出反馈信息,至少包括状态码(通常为枚举类型)、错误信息(通常为string类型)和返回值。我们可以将这些信息依次序列化到Serializer对象,也可以将这些信息进行打包,形成一个独立的类,buttonrpc中的包裹返回值类:

template<typename T>
class value_t {
public:typedef typename type_xx<T>::type type;typedef std::string msg_type;typedef uint16_t code_type;value_t() { code_ = 0; msg_.clear(); }bool valid() { return (code_ == 0 ? true : false); }int error_code() { return code_; }std::string error_msg() { return msg_; }type val() { return val_; }void set_val(const type& val) { val_ = val; }void set_code(code_type code) { code_ = code; }void set_msg(msg_type msg) { msg_ = msg; }friend Serializer& operator >> (Serializer& in, value_t<T>& d) {in >> d.code_ >> d.msg_;if (d.code_ == 0) {in >> d.val_;}return in;}friend Serializer& operator << (Serializer& out, value_t<T> d) {out << d.code_ << d.msg_ << d.val_;return out;}
private:code_type code_;msg_type msg_;type val_;
};

这篇关于远程过程调用-buttonrpc源码解析7-函数返回值的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/874369

相关文章

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生