15

我期待在這個源代碼代碼我從來沒有在C++ 11

template<char... digits> 
struct conv2bin; 

template<char high, char... digits> 
struct conv2bin<high, digits...> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
          conv2bin<digits...>::value; 
}; 

template<char high> 
struct conv2bin<high> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0'); 
}; 

template<char... digits> 
constexpr int operator "" _b() { 
    return conv2bin<digits...>::value; 
} 

int array[1010_b]; 

看到,我想知道這是否是有效的,即使C++。

template<char high, char... digits> 
struct conv2bin<high, digits...> { 

這是什麼?不專門化的模板專業化?

又爲何結構聲明其內部具有行代碼像

struct conv2bin<high> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0'); 
}; 

我很困惑..

+0

是的,抱歉的錯誤 – Paul

+2

看看這些鏈接。他們應該解釋一切。 - [Variadic模板](http://www.cplusplus.com/articles/EhvU7k9E/) - [用戶定義文字](http://en.cppreference.com/w/cpp/language/user_literal) - [Static斷言(http://en.cppreference.com/w/cpp/language/static_assert) –

回答

22

您的代碼顯示了三個新的C++ 11的特點:可變參數模板用戶定義文字靜態斷言

一般可變參數類模板分別指定零個或多個參數,一個或多個專用版本和一個特定版本。

// digits can be the empty set, so 0 or more arguments 
template<char... digits> 
struct conv2bin; 

// digits can be the empty set, so 1 or more arguments 
template<char high, char... digits> 
struct conv2bin<high, digits...> 

// fully specialized for 1 argument 
template<char high> 
struct conv2bin<high> 

的可變參數模板的完整的語法是有點古怪,Wikipedia上有一個像樣的文章。它對於另一個C++ 11功能特別有用:完美轉發可變數量的函數參數。

異國情調的外觀int operator "" _b()定義了一個用戶定義的文字,這是一種將自己的單位添加到您的類型和表達式的方式。它僅僅意味着_b後面的整數被標記爲某個「單位」。有關更多詳細信息,請參閱此question。一個實際的好處是避免將來的火星着陸器崩潰(其中SI和英制單位在他們的着陸軟件中被混合,而編譯器不能診斷它)。

static_assert完全符合您的想法:它靜態地聲明其條件,即在編譯時間。斷言失敗時,編譯將停止。這是儘快發現錯誤的好方法。

UPDATE

的可變參數模板專業化,可當你有的參數部分重疊的範圍非常令人吃驚:零個或多個參數的版本將只匹配在你的榜樣空列表(如果你願意爲它提供了一個定義)。

#include <iostream> 

template<int... Args> 
struct Test 
{ 
    enum { value = 0 }; 
}; 

template<int I, int... Args> 
struct Test<I, Args...> 
{ 
    enum { value = 2 }; 
}; 

template<int I> 
struct Test<I> 
{ 
    enum { value = 1 }; 
}; 

int main() 
{ 
    std::cout << Test<>::value << "\n";  // matches zero or more version 
    std::cout << Test<0>::value << "\n"; // matches single argument version 
    std::cout << Test<0, 0>::value << "\n"; // matches one or more version, not the zero or more one! 
} 

LiveWorkSpace的輸出。

這當然是部分模板專門化的一般規則的一個例子,它指出將選擇最專業版本(一個或多個專用性比零或多個更專門化,因爲後者可以總是在前者可以使用的地方使用,但反之亦然)。但是因爲可變參數模板通常不是彼此「明顯」不同,所以您應該特別注意其部分專業化。

1
template<char... digits> 
struct conv2bin; 

這是一個模板前向聲明。它不必完全定義,因爲如果以不受支持的方式使用它,則會更快地捕獲錯誤(編譯將失敗)。這個特殊的例子不會導致編譯失敗,因爲專業化涵蓋了所有可能的情況。

template<char high, char... digits> 
struct conv2bin<high, digits...> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
          conv2bin<digits...>::value; 
}; 

這是部分專業化,其中設置了一個模板值。剩下的只是轉發到模板類型的「較低層級」。這個模板結構是完全定義的,並且包含一個int成員變量,該值取決於'high'值和下一個模板。

template<char high> 
struct conv2bin<high> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0'); 
}; 

再次部分模板專門化,定義模板參數只包含一個參數在它的列表中的值。

因此,總共這是一個template meta-programming使用可變模板。


靜態斷言用於限制模板變量可以採用的值。