c++ - 实例化和未实例化模板的部分模板特化

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

我有以下两个结构:

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;

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

这里的解决方案是什么?

最佳答案

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

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 的参数有不同的“种类”(“type of type”)。

您可以做什么:

  • 您可以提供 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>
    

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

关于c++ - 实例化和未实例化模板的部分模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55736916/

相关文章:

c++ - 将 constexpr class static 映射到类集合的类

c++ - 使用概念来选择类模板特化

c++ - 循环中前进迭代器

c++ - Visual Studio 中的大括号逗号语法是什么?

c++ - SFINAE 不适用于 constexpr 函数?

templates - 有没有办法从字符串创建可迭代列表?

c++ - 为什么 SFINAE 在更改类模板特化的位置时会搞砸?这是 C++ 错误吗?

c++ - 使用可变参数模板的特化作为模板参数

c++ - 将类常量存储在数据成员中还是方法中更好?

c++ - Bazel:编译单个文件而不链接