繁体   English   中英

在模板特化中强制编译时错误

[英]Force a compile time error in a template specialization

我最近开始学习现代模板元编程,我自己写了一个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");
};

但是每次都会抛出一个编译错误,即使它不匹配。

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

如果将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");
}

要在这里获得一个真正完善的解决方案有点烦人。 你正在遇到[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的解决方案可能会让每个编译器都能得到你,但我可能只是使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM