2013-05-03 48 views
2

我有這樣的代碼,我試圖讓編譯時間訪問與std::get元組。當用戶輸入一個超出元組範圍的數字時,我想拋出一個異常。不幸的是,我不能讓它工作,所以我讓代碼返回數組中的第一個元素,如果它超出範圍。如何可以拋出一個異常時,模板參數是無效的?

#include <tuple> 

template <class... T> 
struct input 
{ 
    std::tuple<T...> var; 
    input(T&&... t) : var(std::forward<T>(t)...) {} 

    template < 
      std::size_t N, 
      bool in_range = 0 <= N && N < std::tuple_size<decltype(var)>::value 
    > 
    auto get() 
      -> typename std::tuple_element<in_range ? N : 0, decltype(var)>::type&& 
    { 
     return std::move(std::get<in_range ? N : 0>(var)); 
    } 
}; 

template <class... Args> 
void f(Args&&... args) 
{ 
    auto arguments = input<Args...>(std::forward<Args>(args)...); 

    arguments.template get<9>(); // returns 2 but I'd rather throw an exception 
} 

int main() 
{ 
    f(2, 4, 6, 8); 
} 

我怎麼能拋出一個異常或者至少是使用static_assert的手段來得到這個工作?

+1

如何加入'static_assert(IN_RANGE, 「???」);'? – 2013-05-03 19:39:16

+0

我試過了。它不會工作,因爲要這樣做,我會改變'tuple_element ''到tuple_element '。這樣的話,會導致編譯錯誤,如果'N'超出範圍(之前它甚至*獲取*評估'static_assert'。 – 2013-05-03 19:41:54

+5

例外是運行時錯誤,而這是一個編譯時錯誤(實際上,它是一個*編程*錯誤,這異常並不意味着處理) – 2013-05-03 19:42:40

回答

3

例外都是爲了報告運行時錯誤,而您正在處理編譯時編程問題

如果您介意編譯器會嘗試實例化tuple_element<>帶出界外的不是非常透明的錯誤一世ndex,你可以使用SFINAE得到避免你的函數的重載解析過程中都得到實例:

​​3210

如果你想增加一個更清晰static_assert(),你可以通過添加只有當得到回升N超載這樣做超出界限:

template<std::size_t N, 
     typename std::enable_if<(N >= std::tuple_size<decltype(var)>::value)>:: 
      type* = nullptr> 
    void get() 
    { 
     static_assert(N < std::tuple_size<decltype(var)>::value, "OOB"); 
    } 

這是live example

2

試試這個:

template <class... Args> 
void f(Args&&... args) 
{ 
    static_assert(sizeof...(Args) > 9, "Invalid tuple size"); 

    auto arguments = input<Args...>(std::forward<Args>(args)...); 

    arguments.template get<9>(); 
} 

(拋出異常是沒有意義的,因爲例外是*出色的運行流量控制」,而不是靜態編譯錯誤檢查。)

相關問題