开源软件:buttonrpc (C++语法分析)

开源软件:buttonrpc (C++语法分析)

本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。

C++ 语法分析

template

template<typename T>

struct type_xx{ typedef T type; };

将T 类型置换为 type

使用:typename type_xx::type ,实际为类型R

typename

"typename"是一个C++程序设计语言中的关键字。当用于泛型编程时是另一术语"class"的同义词。这个关键字用于指出模板声明(或定义)中的非独立名称(dependent names)是类型名,而非变量名。

我们经常会这么用 typename,这是一项C++编程语言的泛型编程(或曰“模板编程”)的功能,typename关键字用于引入一个模板参数。

template <typename T>
const T& max(const T& x, const T& y)
{
  if (y < x) {
    return x;
  }
  return y;
}

在模板定义语法中关键字 class 与 typename 的作用完全一样

template<class T>
const T& max(const T& x, const T& y)
{
  if (y < x) {
    return x;
  }
  return y;
}

这里 class 关键字表明T是一个类型,后来为了避免 class 在这两个地方的使用可能给人带来混淆,所以引入了 typename 这个关键字,它的作用同 class 一样表明后面的符号为一个类型。

那class使用就够了,为什么又引入了新的关键词 typename ,关于这个问题,Stan Lippman 曾在其博客中表示,最早 Stroustrup 使用 class 来声明模板参数列表中的类型是为了避免增加不必要的关键字;后来委员会认为这样混用可能造成概念上的混淆才加上了 typename 关键字。

而使用 typename 的作用就是告诉 cpp 编译器,typename 后面的字符串为一个类型名称,而不是成员函数或者成员变量,这个时候如果前面没有 typename,编译器没有任何办法知道 T::LengthType 是一个类型还是一个成员名称(静态数据成员或者静态函数),所以编译不能够通过。

解决的问题

template<typename T>
void fun(const T& proto){
         T::const_iterator it(proto.begin());
}

发生编译错误是因为编译器不知道T::const_iterator是个类型。万一它是个变量呢? T::const_iterator的解析有着逻辑上的矛盾: 直到确定了T是什么东西,编译器才会知道T::const_iterator是不是一个类型; 然而当模板被解析时,T还是不确定的。这时我们声明它为一个类型才能通过编译:

而且在模板实例化之前,完全没有办法来区分它们,这绝对是滋生各种bug的温床。这时C++标准委员会再也忍不住了,与其到实例化时才能知道到底选择哪种方式来解释以上代码,委员会决定引入一个新的关键字,这就是typename。

C++标准
对于用于模板定义的依赖于模板参数的名称,只有在实例化的参数中存在这个类型名,或者这个名称前使用了 typename 关键字来修饰,编译器才会将该名称当成是类型。除了以上这两种情况,绝不会被当成是类型。

因此,如果你想直接告诉编译器 T::const_iterator 是类型而不是变量,只需用 typename修饰:

typename    T::const_iterator it(proto.begin());

这样编译器就可以确定T::const_iterator是一个类型,而不再需要等到实例化时期才能确定,因此消除了前面提到的歧义。

嵌套从属类型

事实上类型T::const_iterator依赖于模板参数T, 模板中依赖于模板参数的名称称为从属名称(dependent name), 当一个从属名称嵌套在一个类里面时,称为嵌套从属名称(nested dependent name)。 其实T::const_iterator还是一个嵌套从属类型名称(nested dependent type name)。

嵌套从属名称是需要用typename声明的,其他的名称是不可以用typename声明的。比如下面是一个合法的声明:

template<typename T>
void fun(const T& proto ,typename  T::const_iterator it);

std::bind

参考: 当 std::bind 遇上 this

bind本身是一种延迟计算的思想,它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数.

bind能够在绑定时候就同时绑定一部分参数,未提供的参数则使用占位符表示,然后在运行时传入实际的参数值。PS:绑定的参数将会以值传递的方式传递给具体函数,占位符将会以引用传递。众所周知,静态成员函数其实可以看做是全局函数,而非静态成员函数则需要传递this指针作为第一个参数,所以std::bind能很容易地绑定成员函数。

std::bind 遇上 this : 非静态成员函数则需要传递this指针作为第一个参数.

std::is_same<R, void>::value

头文件 : #include <type_traits>

如果两个一样的类型会返回true

std::enable_if

td::enable_if 顾名思义,满足条件时类型有效。作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程(meta programming)中。它的定义也异常的简单:

template <bool, typename T=void>
struct enable_if {
};
template <typename T>
struct enable_if<true, T> {
  using type = T;
};

由上可知,只有当第一个模板参数为 true 时,type 才有定义,否则使用 type 会产生编译错误,并且默认模板参数可以让你不必指定类型。

// help call return value type is void function
template<typename R, typename F>
typename std::enable_if<std::is_same<R, void>::value, typename type_xx<R>::type >::type call_helper(F f) {
	f();
	return 0;
}
// 这里的意思是 如果 

template<typename R, typename F>
typename std::enable_if<!std::is_same<R, void>::value, typename type_xx<R>::type >::type call_helper(F f) {
	return f();
}
std::enable_if<
    std::is_same<R, void>::value, 
    typename type_xx<R>::type 
        >::type
template<typename R>
void buttonrpc::callproxy_(std::function<R()> func, Serializer* pr, const char* data, int len)
{
	typename type_xx<R>::type r = call_helper<R>(std::bind(func));
	value_t<R> val;
	val.set_code(RPC_ERR_SUCCESS);
	val.set_val(r);
	(*pr) << val;
}

template<typename F>
void buttonrpc::callproxy( F fun, Serializer* pr, const char* data, int len )
{
	callproxy_(fun, pr, data, len);
}
template<typename F>
void buttonrpc::bind( std::string name, F func )
{
	m_handlers[name] = std::bind(&buttonrpc::callproxy<F>, this, func, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
}

std::decay

头文件 : #include <type_traits>

对一个类型进行退化处理,如 : cosnt int&退化为int

std::reverse和std::reverse_copy

std::reverse:反转排序容器内指定范围中的元素。std::reverse_copy与std::reverse唯一的区别是:reverse_copy会将结果拷贝到另外一个容器中,而不影响原容器的内容。

std::reverse: defined in header , reverses the order of the elements in the range [first, last).

std::reverse_copy: defined in header , copies the elements in the range[first,last) to the range beginning at result, but in reverse order.

可变参数模板消除冗余代码

// client
template<typename R>
value_t<R> call(std::string name);

template<typename R, typename P1>
value_t<R> call(std::string name, P1);

template<typename R, typename P1, typename P2>
value_t<R> call(std::string name, P1, P2);

template<typename R, typename P1, typename P2, typename P3>
value_t<R> call(std::string name, P1, P2, P3);

template<typename R, typename P1, typename P2, typename P3, typename P4>
value_t<R> call(std::string name, P1, P2, P3, P4);

template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
value_t<R> call(std::string name, P1, P2, P3, P4, P5);
// client
template<typename R, typename... Params>
value_t<R> call(std::string name, Params... ps) {
    using args_type = std::tuple<typename std::decay<Params>::type...>;
    args_type args = std::make_tuple(ps...);

    Serializer ds;
    ds << name;
    package_params(ds, args);
    return net_call<R>(ds);
}

template<typename R>
value_t<R> call(std::string name) {
    Serializer ds;
    ds << name;
    return net_call<R>(ds);
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

002237

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值