【问题标题】:Resolution of class template with different default template argument and partial specialization argument具有不同默认模板参数和偏特化参数的类模板的解析
【发布时间】:2021-12-31 10:48:33
【问题描述】:

我有两个类(结构)模板 AB,除了 第二个参数的默认参数(在它们的主模板中)和 template-specializing第二个论点(在他们的部分特化中)在A相同(都在void),而在B不同voidint)。

#include <bits/stdc++.h>

/* primary class template A */
template <int N, class = void>
struct A : std::false_type {};

/* partial specialization of A */
template <int N>
struct A<N, std::enable_if_t<(N != 0), void>> : std::true_type {};

/* primary class template B */
template <int N, class = void>
struct B : std::false_type {};

/* partial specialization of B */
template <int N>
struct B<N, std::enable_if_t<(N != 0), int>> : std::true_type {};

int main() {

    std::cout << A<0>::value << std::endl; // 0 (i.e. A<0> extends std::false_type)
    std::cout << A<1>::value << std::endl; // 1 (i.e. A<1> extends std::true_type)

    std::cout << B<0>::value << std::endl; // 0 (i.e. B<0> extends std::false_type)
    std::cout << B<1>::value << std::endl; // 0 (i.e. B<1> extends std::false_type)

    return 0;
}

从输出中可以看出,B&lt;1&gt; 解析为主模板,而A&lt;1&gt; 解析为部分特化,我猜这是由于上述差异造成的。这是相当违反直觉的,因为我预计会发生完全相反的情况。但为什么会发生呢?编译器如何决定要解析哪个版本,尤其是在这种情况下?

编辑: 正如@Enlinco 在他的answer 中正确识别的那样,我的困惑是由于期望在实例化B&lt;1&gt; 时,编译器将解析“更专用于N != 0”版本B&lt;N, int&gt;,更喜欢它而不是“更通用" 版本B&lt;N, void&gt;.

【问题讨论】:

  • 我不明白你的困惑。您将A&lt;int&gt; 设计为默认为A&lt;int, void&gt;,然后它使用A&lt;int, void&gt; 的实例化。您将B&lt;int&gt; 设计为默认为B&lt;int, void&gt;,然后它使用B&lt;int, void&gt; 的实例化。您还期望发生什么其他事情?

标签: c++ c++11 template-meta-programming sfinae template-specialization


【解决方案1】:

如果我理解混乱,当你看到

/* primary class template B */
template <int N, class = void>
struct B : std::false_type {};

/* partial specialization of B */
template <int N>
struct B<N, std::enable_if_t<(N != 0), int>> : std::true_type {};

你认为当编译器在main中看到B&lt;1&gt;时,

  • 看通用模板没问题,
  • 然后查看专业化和
    • 看到(N != 0)true
    • std::enable_if_t&lt;(N != 0), int&gt; 解析为int
    • 因此产生B&lt;1, int&gt;,这是一个很好的选择,因为它是一个专业化。

故事略有不同。

线

template <int N, class = void>

只是意味着,正如评论中所建议的那样,当您编写 B&lt;<i>an-int</i>&gt; 时,编译器会看到 B&lt;<i>an-int</i>, void&gt;

如果你从这个角度来看,你应该明白为什么不匹配会导致你观察到的行为:B&lt;1&gt; 只是B&lt;1, void&gt;,没有专门针对它。

【讨论】:

    猜你喜欢
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多