百度apollo源碼學習(一)DEFINE-創(chuàng)新互聯(lián)

文章目錄
  • 前言
  • 源碼
    • 解讀
    • SFINAE機制
    • 舉例
  • 參考

創(chuàng)新互聯(lián)是一家集成都做網(wǎng)站、成都網(wǎng)站制作、網(wǎng)站頁面設(shè)計、網(wǎng)站優(yōu)化SEO優(yōu)化為一體的專業(yè)網(wǎng)站設(shè)計公司,已為成都等多地近百家企業(yè)提供網(wǎng)站建設(shè)服務。追求良好的瀏覽體驗,以探求精品塑造與理念升華,設(shè)計最適合用戶的網(wǎng)站頁面。 合作只是第一步,服務才是根本,我們始終堅持講誠信,負責任的原則,為您進行細心、貼心、認真的服務,與眾多客戶在蓬勃發(fā)展的市場環(huán)境中,互促共生。
前言

最近學習百度apollo源碼,發(fā)現(xiàn)很多看不懂的代碼,因才疏學淺,只能通過上網(wǎng)搜索,逐步理解,然后將理解完成的內(nèi)容再次進行記錄,其中參考了很多其他博主的博客。
我覺得對于程序員來說,看優(yōu)秀的代碼是進步最快的方式,看代碼不僅要看懂代碼,還要看明白設(shè)計者設(shè)計該部分代碼的框架。
廢話不多少,接下來看一下apollo中基于C++類型萃取實現(xiàn)的結(jié)構(gòu)體成員變量或函數(shù)的存在性判斷的宏定義:DEFINE_TYPE_TRAIT該宏定義位于:cyber/base/macros.h中。

源碼
#define DEFINE_TYPE_TRAIT(name, func)                     \
  template   \
  struct name {   \
	// 僅當T是一個類類型時,“Class::func”才是存在的,從而這個泛型函數(shù)的實例化才是可行的
	// 否則,就將觸發(fā)SFINAE
    template \
    static constexpr bool Test(decltype(&Class::func)*) {\
      return true;                                        \
    }                                                     \
    // 僅當觸發(fā)SFINAE時,編譯器才會“被迫”選擇這個版本
    template   \
    static constexpr bool Test(...) { \
      return false;                                       \
    }                                                     \
                                                          \
    static constexpr bool value = Test(nullptr);       \
  };                                                      \
                                                          \
  template   \
  constexpr bool name::value;
解讀

這個宏定義創(chuàng)建了一個struct name的結(jié)構(gòu)體constexpr bool name::value的變量。
第6-15行使用了SFINAE機制,定義了模版類型的Test函數(shù)。具體參看【C++深陷】之“decltype”和C++模板SFINAE特性與反射機制

從名字可以知道這段代碼的目的是定義一個名為name的類型萃取器,這個萃取器的name::value是bool類型,可以判定T中是否有func函數(shù)。使用如下:

DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong)
//定義HasByteSize的結(jié)構(gòu)體,func為ByteSizeLong

DEFINE_TYPE_TRAIT 會根據(jù)宏參數(shù) name 創(chuàng)建一個同名的類型萃取模板類,并檢查模板類型參數(shù) T 中是否包含與宏參數(shù) func 同名的方法,若包含,則模板類的 value 成員被置為 true,否則置為 false。應該注意的是,func 在 T 中必須是公有的,否則無法被發(fā)現(xiàn)。

所以 DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong) 的具體含義是:創(chuàng)建類型萃取模板類 HasByteSize,HasByteSize可檢查模板類型參數(shù) 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可以是結(jié)構(gòu)體或者類。

SFINAE機制

C++模板提供了一個SFINAE(subsitate failure is not an error)的機制(模板匹配失敗不是錯誤),這是模板里面一個非常有意思的特性,利用這個機制可以檢查一個結(jié)構(gòu)體是否包含某個成員等操作。c++語言本身沒有提供反射機制(也有利用pb實現(xiàn)反射),利用SFINAE機制,可以實現(xiàn)類似于反射的功能。

舉例
#include#include// A類型包含size函數(shù)
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中有靜態(tài)的常量value,它的初值是通過調(diào)用結(jié)構(gòu)體的靜態(tài)成員函數(shù)Test(nullptr)來初始化的。
而它有兩個Test函數(shù),且都是constexpr修飾的,這表明函數(shù)參數(shù)及返回值在編譯器就要確定下來。
正是如此,如果Class有size函數(shù),那么

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

在編譯期就可以替換成功,即

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

value = Test(nullptr)也就自然而然被初始化為true。否則,便會是false。
運行上述結(jié)果,因為B::size()不存在,可以看到最后輸出了結(jié)果。

參考

【C++深陷】之“decltype”
C++模板SFINAE特性與反射機制
由一道C++面試題引發(fā)的思考
深入探索單例設(shè)計模式:以百度 Apollo 為例
C++ type_traits和SFINAE的一點理解

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁名稱:百度apollo源碼學習(一)DEFINE-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://bm7419.com/article14/dpoide.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站內(nèi)鏈、網(wǎng)站收錄、定制網(wǎng)站電子商務、網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)