百度apollo源码学习(一)DEFINE-创新互联

文章目录
  • 前言
  • 源码
    • 解读
    • SFINAE机制
    • 举例
  • 参考

创新互联是一家集成都做网站、成都网站制作、网站页面设计、网站优化SEO优化为一体的专业网站设计公司,已为成都等多地近百家企业提供网站建设服务。追求良好的浏览体验,以探求精品塑造与理念升华,设计最适合用户的网站页面。 合作只是第一步,服务才是根本,我们始终坚持讲诚信,负责任的原则,为您进行细心、贴心、认真的服务,与众多客户在蓬勃发展的市场环境中,互促共生。
前言

最近学习百度apollo源码,发现很多看不懂的代码,因才疏学浅,只能通过上网搜索,逐步理解,然后将理解完成的内容再次进行记录,其中参考了很多其他博主的博客。
我觉得对于程序员来说,看优秀的代码是进步最快的方式,看代码不仅要看懂代码,还要看明白设计者设计该部分代码的框架。
废话不多少,接下来看一下apollo中基于C++类型萃取实现的结构体成员变量或函数的存在性判断的宏定义:DEFINE_TYPE_TRAIT该宏定义位于:cyber/base/macros.h中。

源码
#define DEFINE_TYPE_TRAIT(name, func)                     \
  template   \
  struct name {   \
	// 仅当T是一个类类型时,“Class::func”才是存在的,从而这个泛型函数的实例化才是可行的
	// 否则,就将触发SFINAE
    template \
    static constexpr bool Test(decltype(&Class::func)*) {\
      return true;                                        \
    }                                                     \
    // 仅当触发SFINAE时,编译器才会“被迫”选择这个版本
    template   \
    static constexpr bool Test(...) { \
      return false;                                       \
    }                                                     \
                                                          \
    static constexpr bool value = Test(nullptr);       \
  };                                                      \
                                                          \
  template   \
  constexpr bool name::value;
解读

这个宏定义创建了一个struct name的结构体constexpr bool name::value的变量。
第6-15行使用了SFINAE机制,定义了模版类型的Test函数。具体参看【C++深陷】之“decltype”和C++模板SFINAE特性与反射机制

从名字可以知道这段代码的目的是定义一个名为name的类型萃取器,这个萃取器的name::value是bool类型,可以判定T中是否有func函数。使用如下:

DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong)
//定义HasByteSize的结构体,func为ByteSizeLong

DEFINE_TYPE_TRAIT 会根据宏参数 name 创建一个同名的类型萃取模板类,并检查模板类型参数 T 中是否包含与宏参数 func 同名的方法,若包含,则模板类的 value 成员被置为 true,否则置为 false。应该注意的是,func 在 T 中必须是公有的,否则无法被发现。

所以 DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong) 的具体含义是:创建类型萃取模板类 HasByteSize,HasByteSize可检查模板类型参数 T 中是否包含 ByteSizeLong方法。

HasByteSize::value  \\ true 表示有A.ByteSizeLong()
//在宏定义中为name::value,即HasByteSize.value, Test(nullptr)
//这里的模版T就是A,那么4-7行Test模版中Class就是这里的A。
HasByteSize::value  \\ false 表示没有B.ByteSizeLong()

其中A和B可以是结构体或者类。

SFINAE机制

C++模板提供了一个SFINAE(subsitate failure is not an error)的机制(模板匹配失败不是错误),这是模板里面一个非常有意思的特性,利用这个机制可以检查一个结构体是否包含某个成员等操作。c++语言本身没有提供反射机制(也有利用pb实现反射),利用SFINAE机制,可以实现类似于反射的功能。

举例
#include#include// A类型包含size函数
struct A {int size() {  return 0;
  }
};
struct B {int Size() {return 1;
    }
};
// type trait
templatestruct HasSize {templatestatic constexpr bool Test(decltype(&Class::size)*) {return true;
    }
    templatestatic constexpr bool Test(...) {return false;
    }
    static constexpr bool value = Test(nullptr);
};

int main() {if (!HasSize::value) {std::cout<< "hello world"<

上面代码中,HasSize中有静态的常量value,它的初值是通过调用结构体的静态成员函数Test(nullptr)来初始化的。
而它有两个Test函数,且都是constexpr修饰的,这表明函数参数及返回值在编译器就要确定下来。
正是如此,如果Class有size函数,那么

static constexpr bool Test(decltype(&Class::size)*) {return true;
}

在编译期就可以替换成功,即

static constexpr bool Test(Func *) {return true;
}

value = Test(nullptr)也就自然而然被初始化为true。否则,便会是false。
运行上述结果,因为B::size()不存在,可以看到最后输出了结果。

参考

【C++深陷】之“decltype”
C++模板SFINAE特性与反射机制
由一道C++面试题引发的思考
深入探索单例设计模式:以百度 Apollo 为例
C++ type_traits和SFINAE的一点理解

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享题目:百度apollo源码学习(一)DEFINE-创新互联
分享网址:
http://scyanting.com/article/dpoide.html