【问题标题】:Template specialization with variadic non-type arguments具有可变非类型参数的模板特化
【发布时间】:2020-01-22 04:04:09
【问题描述】:

我正在尝试检测一个类型是否属于 A 类型(带有任何模板参数)。我正在为此使用辅助结构和模板专业化。我做了以下事情:

#include <iostream>

template<typename,typename,typename,typename,int... pars> struct A{};

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

template<typename... T>
struct check<A<T...>> : std::true_type{}; // specialization is not applied

template<typename... T, int... pars>
struct check<A<T...,pars...>> : std::true_type{}; // same

// the following would get applied for any A:

// template<typename T1, typename T2, typename T3, typename T4, int... pars> 
// struct check<A<T1,T2,T3,T4,pars...>> : std::true_type{};

int main(){
    std::cout << check<A<int,char,double,int,1,2,3>>::value << std::endl;
}

但是,它将打印出 0,因此未应用未注释的特化。它不应该工作还是我在这里遗漏了什么?是否有类似或替代的方法来检测任何类型 A,而不必像上面注释的行中那样为 A 类写出所有 typename T1 等?

【问题讨论】:

  • 注意:clang 不会编译这个:godbolt.org/z/Eg6cG2 "错误:类模板部分特化包含无法推导的模板参数;这个部分特化永远不会被使用 [-Wunusable-partial-specialization"

标签: c++ templates variadic-templates template-specialization


【解决方案1】:

即使我们的人脑可以推断出非类型参数包旁边的类型参数包,编译器也不愿意尝试找出一个参数包在哪里结束,而另一个参数包从哪里开始。

一般来说,混合可变数量的类型和非类型参数并不是一个好方法。一般的解决方法是,如果您可以修改 A,将非类型参数提升为类型:

template <int... pars>
using make_pars = std::integer_sequence<int, pars...>;

然后,检查就简单多了

template <typename... Ts>
struct check : std::false_type {};

template <typename... Ts>
struct check<A<Ts...>> : std::true_type {};

使用时没有太多额外的样板:

std::cout << check<A<int,char,double,int,make_pars<1,2,3>>>::value << std::endl;

演示:https://godbolt.org/z/7pMp2e

【讨论】:

  • 感谢您的建议。我见过一些使用多个可变参数包的专业化示例,例如godbolt.org/z/2zfpf-。但是,如果它必须将可变参数扩展为彼此相邻的参数,它确实不愿意弄清楚。
猜你喜欢
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多