2013-05-03 64 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>(); 
} 

(抛出异常是没有意义的,因为例外是*出色的运行流量控制”,而不是静态编译错误检查。)

相关问题