当前位置: 首页 > 知识库问答 >
问题:

为什么可变模板的模板特殊化不同于非可变模板的特殊化?

巫马磊
2023-03-14

我不明白为什么可变模板的模板专用化不同于常规(即非可变)模板。例如,我有一个模板和一个专门化,如:

enum class MF : int {
    ZERO = 0,
    ONE = 1,
    TWO = 2
};

// --------- Specialization -------------
template <MF mf>
class Stat{
public:
    Stat(std::string msg) {
        cout << "Generic Stat construtor: " << msg << endl;
    }
};

// --------- Template Specialization -------------
template<>
class Stat<MF::ONE>{
public:
    Stat(std::string msg) {
        cout << "Specialized Stat constructor: " << msg << endl;
    }
};

我专门研究 MF 枚举的特定值。

现在,如果我想专门化一个可变参数模板,我不能用 MF 枚举的特定值来专门化可变参数模板参数(例如,MF:ONE),我只能专门化一个类型(例如 MF)。

// --------- Variadic Template -------------
template<MF mf, typename... E>
class Var{
public:
    Var(std::string msg){
        cout << "Generic Var constructor: " << msg << endl;
    }

};

// --------- Variadic Template Specialization -------------
template<>
class Var<MF::TWO, MF>{
public:
    Var(std::string msg){
        cout << "Specialized Var constructor: " << msg << endl;
    }
};

我想为一个特定的< code>MF值专门化我的变量模板,但是似乎我不能。

我是否遗漏了语言的某些方面,可以让我做我想做的事情?大致如下:

template<>
class Var<MF::TWO, MF::ONE>{
public:
    Var(std::string msg){
        cout << "Specialized Var constructor: " << msg << endl;
    }
};

完整的示例可以在这里找到

共有2个答案

堵宏毅
2023-03-14

模板s不是宏。typename…并不意味着“采用任意数量的逗号分隔字符串”。typename…表示“采用0种或更多类型”。

MF::ONE 不是一个类型。

尝试传递< code>MF::ONE,其中< code >模板需要< code>typename...是错误的,因为< code >模板要求的是< code>typename而不是值。

您可以编写一个模板类,它接受0个或多个MFs。您可以编写一个接受零个或多个类型的模板类。您不能编写一个接受0个或多个MFs或类型的模板类。C不支持这一点。

如果必须通过类型传递值,则有 std::integral_constant

template<MF mf, typename... E>
class Var;
template<>
class Var<MF::TWO, std::integral_constant<MF, MF::ONE>>{
public:
  Var(std::string msg){
    cout << "Specialized Var constructor: " << msg << endl;
  }
};

你会通过 Var 实例化它

您可以创建别名:

template<MF mf> using MF_t=std::integral_constant<MF, mf>;

要使您的代码看起来更好:

template<MF mf, typename... E>
class Var;
template<>
class Var<MF::TWO, MF_t<MF::ONE>>{
public:
  Var(std::string msg){
    cout << "Specialized Var constructor: " << msg << endl;
  }
};
int main() {
  Var<MF::TWO, MF_t<MF::ONE>> instance("hello");;
}

出于元编程目的,有时编写模板是一个明智的想法,因为总是采用类型,而不采用常量,当您需要将常量填充到如上所述的类型中时。然后模板

您可以使用::value访问std::integral_content的值,或者通过构造它并将其转换为该类型的值。(在C 1y和许多C 11编译器中,这种转换是constexpr)。

那又怎样?

 MF x = MF_t<MF::ONE>{};
 MF y = MF_t<MF::ONE>::value;

xy设置为MF::ONE。在这两种情况下,右边应该是编译时表达式,因此:

MF_t< MF_t<MF::ONE>{} >

是与MF_t相同的有效类型(如果写得很愚蠢)

宋鸿云
2023-03-14

如果我理解正确,您希望您的可变参数模板使用任意数量的MF值进行参数化。好吧,不要这样声明:

template<MF mf, typename... E>

…它声明了任意数量的类型参数,但如下所示:

template<MF mf, MF... moreMF>

...它声明任意数量的< code>MF类型的非类型参数。

也就是说,显式专业化对于不同的模板没有什么不同,但你不知怎么忘记了如何在两者之间进行参数化。

 类似资料:
  • 这是我在玩变量模板时遇到的一个问题。我有一些代码,使用专业化来计算参数包中的“有趣”类型,就像这样: 这段代码工作正常,但是如果我想使用相同的方法来计算类模板,我会遇到问题: 上面的代码编译失败,错误是"预期的类型,得到了'向量'"开始的行"结构计数"。我也无法更简单的东西,所有的类模板接受一个参数: 这段代码也无法编译,再次在以“结构计数”开头的行中抱怨“预期的类型,得到了‘_First’”。有

  • Postfix Completion 的介绍 Postfix Completion 功能本质上也是代码模板,只是它比 Live Templates 来得更加便捷一点点而已。具体它是做什么的,我们通过下面一张 Gif 演示图来说明: 如上图标注 1 所示,非空的判断在 Java 代码中应该是非常常见的一句话代码,如果用 Live Templates 当然也是可以快速生成,但是没有上图 Gif 这种

  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 我需要声明一个可以存储不同类型容器的类。也就是说,如果它能处理STD::Bitset和STD::Array就好了。但是,这两个类需要不同的模板参数······是否可能(以及如何)使用模板化模板类和可变模板来声明此类类? 示例(但错误):

  • 我试图在类型s. t上专门化一个类。它忽略了给定类型的恒定性。在这种情况下,该类型是一个模板模板参数: 上面的代码在GCC 4.8.4和clang 5.0(with-std=c 11)中都抱怨bar在与匹配FOFType模板参数化的类一起使用时未定义。即使我删除了sfinae参数,仍然无法找到特化。 这个问题的一个例子可以在这里找到:https://godbolt.org/g/Cjci9C.在上面

  • 我正在使用Apache FOP,并且已经看到:XSL-在XSL:when测试期间转义撇号,用于在XSL:when测试期间转义字符。 但是,我在使用xsl:模板匹配执行相同的等价测试时遇到问题 示例XML 样品XSL PDF格式输出: 当测试成功而模板匹配失败时,xsl: 如果有人能给我指出正确的方向或者告诉我我做错了什么,我会非常感激的。 非常感谢

  • 是否有人知道此显式特化是否有效: clang 主干 (12/3/2013) 给出以下错误: f:...\test.cpp:36:20: 错误: 从类 'O' 中出线定义 “Fun” 没有定义 1生成错误。 任何来自标准的支持参考来证明你的答案将不胜感激! 注意:我有点惊讶这是一个错误——我认为应该为任何以< code >开始实例化“Fun”的模板参数族选择专门化 这是一个叮当的错误还是我期望中的错