【问题标题】:partial specialization on the number of template parameters of template template parameter模板参数的模板参数个数的偏特化
【发布时间】:2020-10-13 12:18:57
【问题描述】:

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

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> {};

【问题讨论】:

  • 我假设您使用的是 clang 编译器?
  • @NutCracker 不错的链接,但这不是骗子。 OP 并没有问他们的解决方案为什么不起作用,他们只是想要一些解决方案。
  • @cigien 啊,你是对的吗?我收回了我的旗帜。谢谢

标签: c++


【解决方案1】:

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

但为了更具体地解决您的问题,无法对模板模板参数的参数数量进行部分专业化。至少,不是你想要的方式......

通常对类型进行部分特化。它可以为模板参数完成,但在这种情况下,不同的特化必须命名一个模板,并且每个特化必须为具有相同数量参数的模板完成。

这可能解释了为什么不允许您尝试定义专业化的方式...

也就是说,可以对具有typename 参数的模板进行特化,以用于容器 类型。也就是说,模板的参数类型已经'declared'我故意使用“声明”这个词......

确实,正如我在“使用模板模板函数获取模板参数数量”的答案中所证明的那样 here,可以注入“随机” 不实例化模板

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

  • 分支。
  • 调度。
  • 派生自不同的实现。
  • 等等……

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


° 怎么能做到这样的专业化?

  • 更详细的回答见我的回答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;
享受吧!

【讨论】:

    猜你喜欢
    • 2013-09-13
    • 2015-02-19
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多