<tbody id="xj1oc"></tbody>

    <bdo id="xj1oc"></bdo><bdo id="xj1oc"><optgroup id="xj1oc"><thead id="xj1oc"></thead></optgroup></bdo>

    現在的位置: 首頁 > 黃專家專欄 > 正文

    模板的 SFINAE 原則

    2014年10月30日 黃專家專欄 ⁄ 共 1704字 ⁄ 字號 評論關閉

    模板函數的重載遵循SFINAE原則(substitution-failure-is-not-an-error):當一個模板函數的返回值或參數類型無效的時候,該實例不會參與重載解析,也不會導致編譯錯誤。

    所以常用 is_same enable_if 等

    is_same 表示兩個類型是否相同 一般來說代碼是這樣實現的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // stl 實現 4.1.2
    template<typename _Tp, _Tp __v>
    struct integral_constant {
      static const _Tp value = __v;
      typedef _Tp value_type;
      typedef integral_constant<_Tp, __v>   type;
    };
    typedef integral_constant<bool, true>     true_type;
    typedef integral_constant<bool, false>    false_type;
    
    // 定義了兩個不同的 class,其中的 value是其值,有true和false兩種
    
    template<typename, typename>
    struct is_same : public false_type { };
    
    // 模板的偏特化
    template<typename _Tp>
    struct is_same<_Tp, _Tp> : public true_type { };

    enable_if 表現的語義如下:

    enable_if?如果 bool 是true,那么其 type 定義為 T 否則無定義

    可能的實現如下:

    1
    2
    3
    4
    5
    6
    template<typename, bool>
    struct enable_if {};
    
    template<typename _Tp>
    struct enable_if<_Tp, true> {
      typedef _Tp type;
    };

    有了這以上兩個描述,我們演示一下模板的 SFINAE 原則:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    namespace test {
      template<typename _Tp, _Tp __v>
        struct integral_constant {
          static const _Tp value = __v;
          typedef _Tp value_type;
          typedef integral_constant<_Tp, __v>   type;
        };
    
      typedef integral_constant<bool, true>     true_type;
      typedef integral_constant<bool, false>    false_type;
    
      // 定義了兩個不同的 class,其中的 value是其值,有true和false兩種
      //
      template<typename, typename>
        struct is_same : public false_type { };
      //
      // 模板的偏特化
      template<typename _Tp>
        struct is_same<_Tp, _Tp> : public true_type { };
    
      template<bool, typename _Tp = void>
        struct enable_if {};
    
      template<typename _Tp>
        struct enable_if<true, _Tp> {
          typedef _Tp type;
        };
    }
    
    class SfinaeTest {
      public:
        void Foo(double) {
          std::cerr << "double" << std::endl;
        }
    
        template<class Tp>
          typename test::enable_if<test::is_same<Tp, int>::value || test::is_same<Tp, std::string>::value>::type
          Foo(Tp t) {
            std::cerr << "Tp" << std::endl;
          }
    };
    
    int main() {
      SfinaeTest s;
      s.Foo(1);               // 成功,能夠推導出 Tp = int
      std::string str;        // 成功,能夠推導出 Tp = std::string
      s.Foo(1.0);             // 成功
    }

    抱歉!評論已關閉.

    黄色电影网址