当模板参数无效时,如何抛出异常?
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>();
}
(抛出异常没有意义,因为异常是用于"异常运行时流控制",而不是用于静态编译错误检查。)
相关文章:
- 从构造函数抛出异常时如何克服内存泄漏
- 函数如何通知用户它基于函数原型抛出异常?
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- VisualStudios 会抛出异常,而代码块不会 [C++]
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- ZMQ::send() 抛出异常并终止 QNX 进程.为什么以及如何从中恢复?
- new(std::nothrow) int[n] 抛出异常
- 为什么g_object_set抛出异常(vcruntime140.dll)?
- 你能防止 std::regex 在无效表达式上抛出异常吗?
- C++子线程抛出异常
- 我们应该在抛出异常之前取消分配内存吗
- 有没有一种方法可以让OpenCLC++绑定为所有错误抛出异常
- 为什么访问模板化变体作为返回值抛出异常
- 如何实现,错误分配中止而不是抛出异常
- std::p riority_queue::p op什么时候会抛出异常
- 在0x5914F3BE抛出异常(基于.dll)
- std::vector 默认构造函数可以抛出异常吗?
- 挂钩创建文件抛出异常:读取访问冲突
- 如果传递给函数的参数的数据类型是字符串类型,则抛出异常
- 当模板参数无效时,如何抛出异常?