在模板专业化中强制编译时错误
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:
If no valid specialization can
be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic
required... If a hypothetical instantiation of a template immediately
following its definition would be ill-formed due to a construct that does not depend on a template parameter,
the program is ill-formed; no diagnostic is required.
所以我们需要做的是避免任何可能做的事情 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");
};
虽然,在实践中, 可能会被每个编译器找到,我可能只会使用它。
我最近开始学习现代模板元编程,并为自己编写了一个 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:
If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required... If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required.
所以我们需要做的是避免任何可能做的事情 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");
};
虽然,在实践中,