C++1z-如果在模板展开过程中出现条件,则引发编译错误
C++1z - Throwing compile error if condition occurs during template unfolding
我正在编写一个模板,该模板定义类型参数包中给定的类型,其位置与传递给模板的数字相同。这是我写的:
template<size_t I, typename T, typename... Ts>
struct get_type {
typedef typename std::conditional<I == 0, T, typename get_type<I-1, Ts...>::type>::type type;
};
template<size_t I, typename T>
struct get_type<I, T> {
// This works only if compiler stops unfolding the template when I == 0
static_assert(I == 0, "get_type - index out of bounds");
typedef T type;
};
这种方法的问题,如果我们写这样的代码:
static_assert(std::is_same<double, get_type<1,int,double,float>::type>::value, "I wanted double!");
编译器仍然将模板"展开"到最后(即使在那之前它应该知道类型,确切地说是I
等于0
的时候),并且在最后I
溢出并且不再等于0,这意味着static_assert
抛出错误,索引I
越界。但是,如果I
确实超出了范围,我仍然希望在编译时以某种方式抛出一个错误。有办法做到这一点吗?
编译器必须展开模板,否则它将不知道type
的类型是什么。
如果索引越界,std::tuple_element_t
已经给出了一个(相当详细的)错误。
template<size_t I, typename... Ts>
using get_type_t = std::tuple_element_t<I, std::tuple<Ts...>>;
通过将其与显式边界检查结合使用,可以生成更直观的错误消息:
template<size_t I, typename... Ts>
struct get_type {
using L=std::tuple<Ts...>;
static_assert(I < 0 || I >= std::tuple_size<L>(), "out of bounds");
using type = std::tuple_element_t<I, L>;
};
template<size_t I, typename... Ts>
using get_type_t = typename get_type<I, Ts...>::type;
这里有一个没有std::tuple
开销的例子(改编自boostcon):
struct empty{};
template<class T>
struct tag_t:empty{};
template<class T>
tag_t<T> tag{};
template <typename ignore>
struct lookup;
template <std::size_t... ignore>
struct lookup<std::index_sequence<ignore...>> {
template <typename nth>
static nth
apply(decltype(ignore, empty())..., tag_t<nth>, ...);
};
template<std::size_t I, class... Ts>
using get_type = decltype(
lookup<std::make_index_sequence<I>>::apply(tag<Ts>...)
);
// Test
static_assert(std::is_same<get_type<1, int, float, int>, float>(), "");
static_assert(std::is_same<get_type<0, int, float, int>, int>(), "");
以下是我得出的答案:
struct error_type {};
template<size_t I, typename T, typename... Ts>
struct get_type {
typedef typename std::conditional<I == 0, T, typename get_type<I-1, Ts...>::type>::type type;
static_assert(!std::is_same<type, error_type>::value, "get_type - index out of bounds");
};
template<size_t I, typename T>
struct get_type<I, T> {
typedef typename std::conditional<I == 0, T, error_type>::type type;
};
但这似乎有点冗长(我们正在创建一个虚拟结构),所以我留下这个问题,以防有人想出比我的解决方案更聪明的东西。。。
相关文章:
- 在条件变量中触发错误信号的频率是多少
- 更改条件段错误
- 如果语句错误地读取字符串,则始终在第一个条件返回
- 为什么在环路条件中使用'<='而不是'<'会产生分段错误 [SIGSEGV]?
- 虽然循环即使应用了错误条件也不会退出
- 条件变量:wait_for.gcc错误
- C++代码在 for 循环的条件下给出运行时错误,而如果它被具有相同意义的代码替换,则编译正确
- 将子字符串与字符串数组进行比较的 IF 条件会在C++中产生错误
- 功能或条件错误
- 在 constexpr-if 条件下比较 constexpr 函数参数会导致错误
- 输出错误命令的条件语句
- 条件变量和#pragma Pack错误
- C++条件给出错误
- while 循环在传递错误条件时无法退出
- 在if-Statement条件下与分配有关的错误
- 如何编写一个通用函数,该通用函数在没有任何条件和条件的情况下工作(无论是真实和错误)
- 在C 中使用三元运算符始终返回错误条件
- 可理解的种族条件错误导致安全缺陷
- 循环终止条件错误的 cpp 向量
- Fmod为While循环条件错误