假设我们有这样的元函数:
template<typename LHS , typename RHS>
struct add;
我们有一组已知类型的专业化。例如,整数包装器:
template<typename T1 , T1 VALUE1 , typename T2 , T2 VALUE2>
struct add<std::integral_constant<T1,VALUE1>,std::integral_constant<T2,VALUE2> : public std::integral_constant<std::common_type_t<T1,T2>,VALUE1+VALUE2> {}; //Take advantage of C++14 helpers
几天前,我们创建了一个新类,我们专门为这个类增加了一个:
template<typename X , typename Y>
struct point_2d
{
using x = X;
using y = Y;
};
template<typename X1 , typename Y1 , typename X2 , typename Y2>
struct add<point_2d<X1,Y1>,ppoint_2d<X2,Y2>> : public point_2d<add<X1,X2>,add<Y1,Y2>> {};
如您所见,我使用add
metafuntion来执行坐标的添加。因此,任何具有添加元函数专门化的类型都可以用作point_2d
坐标。
我的问题是:有没有办法检查模板是否具有给定类型作为参数的特化?
这样的事情:
template<template<typename...> class TEMPLATE , typename... Ts>
struct has_specialization;
template<template<typename...> class TEMPLATE , typename... Ts>
struct has_specialization<TEMPLATE<Ts...> /* TEMPLATE<Ts...> exists */ , Ts...> : public std::true_type {};
template<template<typename...> class TEMPLATE , typename... Ts>
struct has_specialization<TEMPLATE<Ts...> /* TEMPLATE<Ts...> doesn't exists */ , Ts...> : public std::false_type {};
答案 0 :(得分:7)
@BartekBanachewicz的想法是通过断言提供用户友好的编译器错误。 如果我可以检查(跟随point_2d示例),如果传递的坐标是可添加的 (也就是说,是否为该坐标定义了添加元函数的特化), 我可以提供更多可读错误,例如“那个坐标不可添加.point_2d需要 点加法的可添加坐标“,而不是常见的可怕模板瞬时错误。
鉴于这是你的问题的动机,这不是一个 更简单,更直接的解决方案:
#include <type_traits>
template<typename LHS , typename RHS>
using cannot_add = std::integral_constant<bool,std::is_same<LHS,LHS>::value>;
template<typename LHS , typename RHS>
struct add
{
/* Assert some expressively named condition that is always false
but is dependent on a template parameter.
*/
static_assert(!cannot_add<LHS,RHS>::value,
"Types are not addable. Need specialization");
};
template<typename T1 , T1 VALUE1 , typename T2 , T2 VALUE2>
struct add<std::integral_constant<T1,VALUE1>,std::integral_constant<T2,VALUE2>>
: public std::integral_constant<
typename std::common_type<T1,T2>::type,
VALUE1+VALUE2
> {};
int main()
{
add<std::integral_constant<int,1>,std::integral_constant<int,2>> x; // Line 25
add<float,float> y; // Line 26
return 0;
}
GCC 4.8.1诊断:
main.cpp:26:19: required from here
main.cpp:12:2: error: static assertion failed: Types are not addable. Need specialization
Clang 3.3诊断:
main.cpp:12:2: error: static_assert failed "Types are not addable. Need specialization"
static_assert(!cannot_add<LHS,RHS>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:26:19: note: in instantiation of template class 'add<float, float>' requested here
add<float,float> y; // Line 26
^