2014-07-23 73 views
1

我想實現一個基本的模板元編程結構,該結構使用std::is_same來確定類型列表是否全部相同。我試圖執行它,如下所示:瞭解爲什麼編譯時布爾代數不起作用

template <typename T, typename U, typename... Args> 
struct check_same { 
    static const bool value = std::is_same<T, U>::value && check_same<U, Args...>::value; 
}; 

template <typename T, typename U> 
struct check_same { 
    static const bool value = std::is_same<T, U>::value; 
}; 

但是,如果我嘗試實例check_same我得到以下編譯器錯誤:

'check_same' : too few template arguments

這是爲什麼不進行編譯時布爾的有效方法代數?當然,由於涉及的所有表達式都是constexpr(或const,因爲MSVC尚未實現constexpr),它應該編譯?


下面將無法被編譯:在C++

int main() 
{ 
    static_assert(check_same<int, unsigned int, float>::value, "Types must be the same"); 

    return 0; 
} 
+0

您缺少'value'類型。不知道這與你的錯誤有什麼關係。 – chris

+0

[看到這個答案是一個偉大的'are_same'實現](http://stackoverflow.com/a/24687161/701092) – 0x499602D2

+0

「太少的模板參數」,因爲通過這個遞歸,args消耗到0,並且沒有check_same < >少於2個強制性參數。 – Solkar

回答

4

類模板不能 「重載」 等的功能。您不能用一組不同的參數重複聲明同一個模板,並期望它能夠進行編譯。例如,這不會編譯

template <typename A> struct S {}; 
template <typename A, typename B> struct S {}; 

它不能編譯,因爲它試圖聲明模板類S兩次。這是非法的。

您的代碼存在完全相同的錯誤:您已聲明模板check_same兩次。你不能那樣做。

您顯然嘗試使用的技術應該基於模板專業化,而不是模板重新聲明。你必須聲明你主要模板只有一次

template <typename T, typename U, typename... Args> 
struct check_same { 
    static const bool value = std::is_same<T, U>::value && check_same<U, Args...>::value; 
}; 

,然後提供主模板的偏特特定,更受限制的組參數

template <typename T, typename U> 
struct check_same<T, U> { 
    static const bool value = std::is_same<T, U>::value; 
}; 
2

試試這個:

template <typename T, typename... Args> 
struct check_same: std::true_type {}; 

template <typename T, typename U, typename...Args> 
struct check_same<T,U,Args...>: std::integral_constant<bool, 
    std::is_same<T,U>::value && check_same<U, Args...>::value 
> {}; 

第一個只有在只有一個參數時纔會評估。第二個專業獲得2個或更多。

如果您傳遞0個參數,則會出錯。我認爲,你應該處理以及:

template <typename... Args> 
struct check_same: std::true_type {}; 

template <typename T, typename U, typename...Args> 
struct check_same<T,U,Args...>: std::integral_constant<bool, 
    std::is_same<T,U>::value && check_same<U, Args...>::value 
> {}; 

這實際上需要沒有更多的專業化,作爲第一個同時適用於0和1的說法。

+0

@dyp這是如何減少實例化數量的?你會得到3種類型的每個遞歸實例,和我一樣嗎? – Yakk

+0

這是一種短路:當一個檢查返回「false」並且其餘的檢查沒有執行時,遞歸結束。但是,由於'conditional',每步都會有一個實例化,所以它可能不值得。 – dyp

+0

@dyp有條件的兩個分支都被完全評估,所以檢查被執行,只是被丟棄。爲了解決短路問題,您需要做更多的工作,而不是「有條件的」。 – Yakk