【问题标题】:Force a compile time error in a template specialization在模板特化中强制出现编译时错误
【发布时间】:2015-10-29 12:14:56
【问题描述】:

我最近开始学习现代模板元编程,并为自己编写了一个类型的 index_of 函数。

template<std::size_t Index, class C, class A> struct mp_index_of_impl{};
template<std::size_t Index, class C,template<class...> class A,class ...Ts>
struct mp_index_of_impl<Index,C,A<C,Ts...>>{
    using type = std::integral_constant<std::size_t,Index>;
};
template<std::size_t Index, class C,template<class...> class A,class ...Ts,class T1>
struct mp_index_of_impl<Index,C,A<T1,Ts...>>{
    using type = typename mp_index_of_impl<Index + 1,C,A<Ts...>>::type;
};
template<std::size_t Index, class C,template<class...> class A> struct mp_index_of_impl<Index,C,A<>>{
    //static_assert(false,"Does not contain type");
    using type = std::integral_constant<std::size_t,0>;
};

问题是我最后的专长

template<std::size_t Index, class C,template<class...> class A> 
struct mp_index_of_impl<Index,C,A<>>{
      //throw a compile error here
};

我尝试像这样使用 static_assert

template<std::size_t Index, class C,template<class...> class A> struct mp_index_of_impl<Index,C,A<>>{
    static_assert(false,"Does not contain type");
};

但是这样每次都会抛出编译错误,即使不匹配也是如此。

如果匹配此模板特化,我想抛出带有自定义错误消息的编译错误。我该怎么做?

【问题讨论】:

标签: c++ templates c++11 template-meta-programming


【解决方案1】:

如果您将static_assert(false,...) 放入模板特化中,则始终无法从中生成有效代码。这是格式错误,不需要诊断

解决方法是让您的 static_assert 依赖于模板参数:

template<typename T>
struct assert_false : std::false_type
{ };

template <typename T>
inline T getValue(AnObject&)
{
    static_assert( assert_false<T>::value , "Does not contain type");
}

【讨论】:

  • 谢谢这实际上是我的第二次尝试,它有效。 static_assert(Index == 0,"Does not contain type");
  • @Barry 真的吗?但是有人可能会出现并专门为 assert_false 提供一些 T 以继承 std::true_type
  • @TartanLlama 直到有人这样做,它是。大概你不希望他们这样做。
  • @Barry 但是你不知道assert_false 是否专门用于某些T,直到你尝试实例化它。您参考的是哪个标准段落?
  • @TartanLlama 在标准的“格式错误,不需要诊断”(我通常搜索“不需要诊断”)中,该短语的实例屈指可数。
【解决方案2】:

在这里获得一个真正格式良好的解决方案有点烦人。你遇到了 [temp.res]/8:

如果没有有效的专业化可以 为模板生成,并且该模板未实例化,模板格式错误,无诊断 需要...如果模板的假设实例化立即 由于不依赖于模板参数的构造,遵循其定义将是格式错误的, 程序格式错误;不需要诊断。

所以我们需要做的是避免任何可以做的事情static_assert(false, ...)。在这种情况下,我们有一个部分开放。我们可以专注于我们只剩下一种类型的情况,并断言这就是我们正在寻找的:

template<std::size_t Index, class C,template<class...> class A, class Last>
struct mp_index_of_impl<Index,C,A<Last>>{
    static_assert(std::is_same<C, Last>::value,"Does not contain type");
    using type = std::integral_constant<std::size_t, Index>;
};

这不会处理空列表的情况,但在顶层您可以添加另一个 static_assert 以表示非空:

template<std::size_t Index, class C,template<class...> class A>
struct mp_index_of_impl<Index,C,A<>>{ };

template <typename T> is_empty : std::false_type { };
template <template <class...> class A> is_empty<A<>> : std::true_type { };

template <class C, class X>
struct mp_index_of
: mp_index_of_impl<0, C, X>
{
    static_assert(!is_empty<X>::value, "Does not contain type");
};

尽管在实践中,TartanLlama's solution 可能会通过每个编译器让您获得,而我可能只会使用它。

【讨论】:

    猜你喜欢
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    相关资源
    最近更新 更多