统一类型和非类型模板参数
我有一个类型特征,它检查给定类型是否是给定类模板的实例:
I have a type trait that checks if a given type is an instance of a given class template:
template <template <typename...> class C, typename T>
struct check_is_instance_of : std::false_type { };
template <template <typename...> class C, typename ...Ts>
struct check_is_instance_of<C, C<Ts...>> : std::true_type { };
template <template <typename...> class C, typename T>
struct is_instance_of : check_is_instance_of<C, std::remove_cv_t<T>> { };
不幸的是,这不适用于非类型模板参数,因为它们不会被可变参数模板参数捕获",所以
Unfortunately, this does not work for non-type template parameters as they are not "captured" by the variadic template parameters, so
is_instance_of<std::integral_constant, std::true_type>
产生编译错误.有什么方法可以编写 is_instance_of
的实现,该实现可用于任意数量的类型和非类型模板参数?
yields a compile-error. Is there any way to write an implementation of is_instance_of
that works for an arbitrary number of type and non-type template parameters?
我认为没有一种干净的方法可以做到这一点除非,非类型参数都具有相同的类型,并且你知道它是哪种类型.在这种非常特殊的情况下,可以使用函数重载.
I don't think there is a clean way to do this unless the non-type arguments are all of the same type and you know which type it is. In that very specific case, function overloading can be used.
在任何其他情况下,您最终都会遇到完美转发问题的模板参数版本,在该模板变量版本中,您将必须专门处理每种类型/非类型参数组合.
In any other case, you end up in a template-argument version of the perfect forwarding problem where you would have to specialize for every type/nontype argument combination.
如果您只需要处理同类非模板参数,并且可以猜测类型,则应该可以执行以下操作.您可以为不同的类型重载instance_of(此处仅覆盖int),但是您必须为每种希望处理的类型显式创建一个实例:
If you only need to address homogeneous non-template arguments and you can guess the type, the following should work. You can overload instance_of for different types (only int is covered here), but you'd have to explicitly create an instance for each type you want to be able to handle:
// variation for non-type parameters, only for uniform parameters with
// known type.
template <typename V, template <V...> class C, typename T>
struct check_is_instance_of_nontype : std::false_type { };
template <typename V, template <V...> class C, V... Values>
struct check_is_instance_of_nontype<V, C, C<Values...>> : std::true_type { };
// this is as in your example
template <template <typename...> class C, typename T>
struct check_is_instance_of : std::false_type { };
template <template <typename...> class C, typename ...Ts>
struct check_is_instance_of<C, C<Ts...>> : std::true_type { };
template <template <typename...> class C, typename T>
struct is_instance_of : check_is_instance_of<C, std::remove_cv_t<T>> { };
template <template <typename...> class C, typename T>
constexpr bool instance_of()
{
return is_instance_of< C, T>::value;
}
template <template <int...> class C, typename T>
constexpr bool instance_of()
{
return check_is_instance_of_nontype< int, C, T>::value;
}
template< int... >
struct Duck
{
};
template<typename A, typename B>
struct Swallow
{
};
int main() {
typedef Duck<1, 2> SittingDuck;
typedef Swallow< int, int> UnladenSwallow;
std::cout << instance_of< Duck, SittingDuck>() << instance_of< Swallow, UnladenSwallow>();
return 0;
}