[英]How can I throw an exception when a template argument is invalid?
我有這段代碼,我試圖通過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
技巧使此異常起作用?
當您在此處處理編譯時編程問題時,異常旨在報告運行時錯誤。
如果您介意不是非常透明的錯誤,編譯器會為您嘗試使用越界索引實例化tuple_element<>
提供幫助,則可以使用SFINAE來防止在重載解析期間完全實例化您的函數:
template <class... T>
struct input
{
std::tuple<T...> var;
input(T&&... t) : var(std::forward<T>(t)...) {}
template<std::size_t N,
typename std::enable_if<(N < std::tuple_size<decltype(var)>::value)>::
type* = nullptr>
auto get() -> typename std::tuple_element<N, decltype(var)>::type&&
{
return std::move( std::get<N>(var) );
}
};
如果您想添加一個更清晰的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");
}
這是一個生動的例子 。
嘗試這個:
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>();
}
(拋出異常是沒有意義的,因為異常是針對* exception運行時流控制的,而不是針對靜態編譯錯誤檢查的。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.