2017-04-26 43 views
2

我遇到了這個帖子: Convert a number to a string literal with constexpr如何解釋變量模板中的繼承?

答案是相當有趣:

namespace detail 
{ 
    template<unsigned... digits> 
    struct to_chars { static const char value[]; }; 

    template<unsigned... digits> 
    const char to_chars<digits...>::value[] = {('0' + digits)..., 0}; 

    template<unsigned rem, unsigned... digits> 
    struct explode : explode<rem/10, rem % 10, digits...> {}; 

    template<unsigned... digits> 
    struct explode<0, digits...> : to_chars<digits...> {}; 
} 

template<unsigned num> 
struct num_to_string : detail::explode<num> {}; 

我的問題是:

  1. 「結構爆炸:爆炸」 宣佈爆炸的爆炸繼承;如何「結構爆炸< 0,數字...>:to_chars」?

  2. '0'作爲第一個模板參數的函數是什麼?

謝謝!

回答

6

這是一個具有局部特化的遞歸公式,用作終止條件。

explode<1234> 

繼承:

explode<123, 4>   // 1234/10 = 123, 1234 % 10 = 4 

繼承:

explode<12, 3, 4>  // 123/10 = 12, 123 % 10 = 3 

繼承:

explode<1, 2, 3, 4>  // 12/10 = 1, 12 % 10 = 2 

繼承:

explode<0, 1, 2, 3, 4> // 1/10 = 0, 1 % 10 = 1 

此時,最左邊的值(在主模板被稱爲rem)是0,所以它的部分特相符:

template <unsigned... digits> 
struct explode<0, digits...> : to_chars<digits...> {}; 

(表示整數被變成單獨的數字),其最終從繼承:

to_chars<1, 2, 3, 4> 

最後,to_chars的參數包擴展到char陣列,也轉動位數成字符,使1變得'1'2變得'2',等:

const char to_chars<1, 2, 3, 4>::value[] = { '1', '2', '3', '4', 0 }; 

這裏,0是空終止字符,以便value可以被視爲好像它是一個字符串。

+0

非常有趣的是,它「繼續」通過variadiac模板擴展繼承而來,然後從最後一個不同的結構體繼承(base case)。謝謝! – Hei