模板参数的模板参数个数的部分专门化

  • 本文关键字:参数 专门化 c++
  • 更新时间 :
  • 英文 :


假设我有一个这样的模板:

template<template<typename...> class>
struct MyTrait;

MyTrait接受具有任意数量参数的模板作为参数。现在我需要知道传递给MyTrait的模板的模板参数的数量。但像下面这样的专业化是行不通的。

template<template<typename> class T>
struct MyTrait<T> {}; // error: partial specialization cannot match argument list for primary template
template<template<typename, typename> class T>
struct MyTrait<T> {};

在这个答案的底部,有关于如何解决此类问题的更多信息和示例

但更具体地说,不能对模板模板参数的参数数量进行部分专门化。至少,不是你尝试的方式…

部分专门化通常在类型上进行。可以对模板参数执行此操作,但在这种情况下,不同的专门化必须名称一个模板,并且每个专门化必须对具有相同数量参数的模板执行。

这可能解释了为什么你试图定义专业化的方式是不允许的。。。

也就是说,对于容器的类型,可以对具有typename参数的模板进行专门化。也就是说,具有其参数类型的模板已经"声明">我故意用"声明"这个词

事实上,正如我在";使用模板模板函数"获取模板参数的数目在这里,可以注入";"随机">参数到模板中,而不实例化它。

这个特性可以用很多不同的方式来定义模板的专业化,例如:

  • 分支
  • 调度
  • 衍生自不同的实现
  • 等等

这个答案底部的代码(取自我的另一个答案(,显示了一种利用该语言提供的工具的简单方法。。。


°如何才能做到这样的专业化

  • 有关更详细的答案,请参阅此处的答案

但是为了防止您到处寻找一些工作代码,下面的代码是一个可以用于基于模板模板参数专门化模板的解决方案。

它应该是不言自明的。。。

// Helper to make the static_assert 'name-dependent'.
template<typename...> using AlwaysFalse = std::false_type;
// Primary template should only signal the error...
template<typename Trait>
struct ImplSelect {
static_assert(
AlwaysFalse<Trait>::value,
"Missing specialization..."
);
};
// Specialization for a template with one type parameter.
template<template <typename> class Trait, typename T>
struct ImplSelect<Trait<T>> { using Type = Trait<int>; };
// Specialization for a template with two type parameters.
template<template <typename, typename> class Trait, typename T, typename U>
struct ImplSelect<Trait<T, U>> { using Type = Trait<int, int>; };
/* [ Note ] These are ONLY forward declarations.
*          They aren't instatiated within this code.
*/
template<typename T>             struct Victim1;
template<typename T, typename U> struct Victim2;
/* [ Note ] Opaque type tags (forward declarations).
*          Allows for further tag dispatching if desired.
*/
struct Tag1; struct Tag2;
/* Selection of Victim1<int> and Victim2<int, int>.
* Not instantiated yet...
*/
using Impl1 = typename ImplSelect<Victim1<Tag1>>::Type;
using Impl2 = typename ImplSelect<Victim2<Tag1, Tag2>>::Type;
享受吧

最新更新