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 参数的模板进行特化,以用于容器 类型。也就是说,模板的参数类型已经“声明”我故意使用“声明”这个词......

的确,正如我在对“使用模板函数获取模板参数的数量” 的回答中所展示的那样 here ,可以将“随机”参数注入(inject)模板而无需实例化

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

  • 分支。
  • 调度。
  • 源自不同的实现。
  • 等等...

此答案底部的代码(按原样取 self 的另一个答案),展示了一种利用该语言的工具的简单方法提供...


° 如何进行这样的特化?

  • 要获得更详细的答案,请参阅我的答案 here

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

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

// 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;
尽情享受吧!

https://stackoverflow.com/questions/64335133/

相关文章:

c# - 无法在启动类中注入(inject)IAntiforgery

html - 使一个 div 填充具有未指定尺寸的表格单元格的整个宽度和高度

javascript - 在输入焦点上移动/动画占位符

reactjs - 在 useEffect Hook 中使用 axios 取消 token 时如何修

asp.net-core - 我可以在 AspNetCore WebAPI 中将 Cancellat

python - 我试图将 python 文件转换为 exe 文件,但它不起作用

javascript - 错误 : Jmeter: Typed variable declarati

angular - 如何限制 NgSelect 下拉面板中显示的项目数?

reactjs - typescript 错误对象的类型为 'unknown'

reactjs - Chrome,Edge - 禁用字段的自动填充/自动完成