【问题标题】:Partial template specialization over instantiated and uninstantiated template实例化和未实例化模板的部分模板特化
【发布时间】:2019-04-17 22:42:29
【问题描述】:

我有以下两个结构:

template<typename T>
struct one { /* ... */ };

template<template<typename...> typename T>
struct two { /* ... */ };

当我有这样的示例实例化/未实例化模板时:

template<typename T>
struct sample_templated { /* ... */ };

using instantiated = sample_templated<double>;

那我就可以了

one<instantiated>{};
two<sample_templated>{};

很好。不过,我想合并 onetwo 的定义,使它们具有相同的名称,因为这将允许递归。

我尝试使用默认定义,例如

template<typename...>
struct types_match_impl;

并让两个原始结构成为 this 的部分特化,但这与 two 不兼容。

这里的解决方案是什么?

【问题讨论】:

  • 目前还不清楚你到底想要什么,但我猜你想将types_match_impl 传递给它自己。你能展示你想写的代码,并描述你认为它应该做什么吗?

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


【解决方案1】:

您希望的方式是不可能的。原因如下:

one<instantiated>{};
two<sample_templated>{};

one“使用”多于two:它指的是instantiated,即sample_templated实例化double。另一方面,two 只是“使用”sample_templated

当您将模板视为类型上的函数时,这会变得更加清晰:two 是一个接受(类型级)函数来创建某种类型的函数。 one 是一个接受类型来创建某种类型的函数:

one :: T -> one<T>
two :: (T -> U) -> two<(T -> U)>

换句话说,one 的参数与two 的参数具有不同的“种类”(“类型的类型”)。

你可以做什么:

  • 您可以提供one 的特化,它接受模板模板参数(“类型级函数”)模板参数:

    template<template<typename...> typename TT, typename T>
    struct one<TT<T>>  { /* ... */ }; // this basically "calls" TT
    
  • 您可以将two 变成可以同时接受两者的东西,尽管使用“虚拟”模板模板参数:

    template<template<typename...> typename TT, typename... Ts>
    struct two { /* */ };
    
    template<typename...>
    struct Void;
    
    template<typename T>
    struct two<Void<>, T> { /* Use T like in one */ };
    // or derive from one<T>
    

可能还有更多方法,但这些取决于您的具体用例。

【讨论】:

  • 谢谢,我明白了。该解决方案看起来很有希望,我会返回我的结果(PS:喜欢投入的 Haskell :))
  • 不幸的是,不可能在同一个可变参数包中同时拥有两种“种类”的类型,所以我想象中的递归是不可能的
  • 事实证明,对于我的设计,我什至不需要未经实例化的模板,但这些信息将对未来有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-06
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多