std::is_same使用很簡單 重點在於對原始碼的解讀
參考下面一句靜態斷言:
static_assert(!std::is_same<bool, T>::value, "vector<bool> is abandoned in mystl");
靜態斷言優點:可以自定義斷言失敗之後的輸出 便於debug找問題
其中我們用到了std::is_same
點進is_same進行原始碼分析:
template<typename, typename>
struct is_same
: public false_type { };
template<typename _Tp>
struct is_same<_Tp, _Tp>
: public true_type { };
可以看出兩種is_same分別繼承於兩個不同的結構體
再來看看false_type和true_type的定義:
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
可以看出這兩個來自於同一個結構體模版:integral_constant
繼續看integral_constant的定義:
template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
constexpr operator value_type() const noexcept { return value; }
#if __cplusplus > 201103L
#define __cpp_lib_integral_constant_callable 201304
constexpr value_type operator()() const noexcept { return value; }
#endif
};
下面的巨集定義不用管
可以看出這個模版需要一個_Tp類 然後還需要一個非模版型別的引數_v 並且這個引數的型別和_Tp的型別相同 並且會把這個非模版型別引數_v賦值給結構體成員變數
記得我們最開始呼叫is_same時
static_assert(!std::is_same<bool, T>::value, "vector<bool> is abandoned in mystl");
原來斷言的就是這個value的值(一定是個bool且必須是個bool)
回到上一步false_type和true_type的定義:
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
可以看出實際上是起了兩個別名 true_type結構體中包含的value成員變數一定是true flase_type結構體中包含的value成員變數一定是false 我們需要斷言的也就是這個value的值 再往回導一步:
template<typename, typename>
struct is_same
: public false_type { };
template<typename _Tp>
struct is_same<_Tp, _Tp>
: public true_type { };
這個是模版呼叫優先順序的問題 實際上 當傳入相同型別的引數時(std::is_same<bool, bool>)此時會直接呼叫下面的is_same 反之如果兩個型別不同 則會呼叫上面的is_same
所以最開始我們的呼叫:
static_assert(!std::is_same<bool, T>::value, "vector<bool> is abandoned in mystl");
這裡的實際要求是不能傳入bool型別的變數 即vector不接受bool型別
這設計思路真的很棒
原始碼地址是github上開源的自己手寫STL