【问题标题】:Role of default template arguments in the context of partial specialization默认模板参数在部分特化上下文中的作用
【发布时间】:2018-10-01 02:16:19
【问题描述】:

我不清楚在部分专业化的上下文中默认模板参数的交互,以选择哪个是更好的匹配模板。这个问题源于 max66 在answer 中发布的代码。

给定类A和B的定义:

template <int N> struct A { static const int code = N; };

struct B{};

以及以下模板类:

// primary template
template <typename, typename Enable = bool_constant<true>>
struct cond : public bool_constant<false> {};

// specialization
template <typename T>
struct cond<T, bool_constant<(0 == T::code)>> : public bool_constant<true> {};

1) cond&lt;B&gt;::value 的计算结果为 false(即选择了主节点)。这很清楚,因为主模板产生 cond&lt;B, bool_constant&lt;true&gt;&gt;,特化失败,因此主模板是唯一可能的选择。

2) cond&lt;A&lt;0&gt;&gt;::value 计算结果为 true(即选择专业化)。这很清楚,因为主模板产生cond&lt;B, bool_constant&lt;true&gt;&gt;,特化也产生cond&lt;B, bool_constant&lt;true&gt;&gt;,因此特化是首选,因为第二个模板参数的参数是明确给出的。

3) cond&lt;A&lt;1&gt;&gt;::value 计算结果为 false(即选择了主节点)。这对我来说不是很清楚。主模板产生cond&lt;B, bool_constant&lt;true&gt;&gt;,专业化产生cond&lt;B, bool_constant&lt;false&gt;&gt;。鉴于第二个模板参数的参数在特化中明确给出,为什么不是首选?

我认为(3)中的行为是由于主模板的默认模板参数和专业化之间的一些交互。在这个answerJerry Coffin 中陈述了一些可以解释这种行为的东西:

如果我们改变专业化,使其专业化 用于基本模板提供的默认类型以外的类型 然后将选择基本模板。

有人可以详细说明这条规则吗?谢谢

【问题讨论】:

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


    【解决方案1】:
    template <typename, typename Enable = bool_constant<true>>
    struct cond : public bool_constant<false> {};
    

    等同于

    template <typename, typename Enable = bool_constant<true>> struct cond;
    
    template <typename, typename Enable>
    struct cond : public bool_constant<false> {};
    

    稍后可能会更清楚地理解结果。

    当你写cond&lt;C&gt;时,由于默认参数,它相当于cond&lt;C, bool_constant&lt;true&gt;&gt;。

    然后我们尝试将其与“更好的实例化”相匹配。

    我们可以选择:

    // primary template
    template <typename, typename Enable>
    struct cond : public bool_constant<false> {};
    

    和使用 SFINAE 的部分专业化:

    // specialization
    template <typename T>
    struct cond<T, bool_constant<(0 == T::code)>> : public bool_constant<true> {};
    

    如果0 == T::code 格式不正确,则丢弃专业化,只有主模板是可行的解决方案,因此使用它。

    否则,如果 0 == T::code 计算结果为 false,则特化不匹配,并且还使用主模板。
    请注意,在这种情况下,使用 cond&lt;C, bool_constant&lt;false&gt;&gt; 将使用专业化。

    否则,0 == T::code 评估为 true,然后初级和专业化都可行,但专业化更专业化,因此被选中。

    【讨论】:

    • 您能否详细说明0 == T::code 评估为false 的情况?为什么不匹配?为什么显式使用 cond&lt;C, bool_constant&lt;false&gt;&gt; 会匹配?
    • 正如我所说,cond&lt;C&gt; 是 cond&lt;C, bool_constant&lt;true&gt;&gt; 和 cond&lt;C, bool_constant&lt;true&gt;&gt; 不匹配 cond&lt;T, bool_constant&lt;false&gt;&gt;(T == C 但 true != false)。
    • 我还是一头雾水。我可以看到它不匹配。问题是,为什么它应该匹配为有效的专业化?我对默认模板参数的理解是,如果没有特别提供,则使用默认值。但是,如果显式提供了任何有效类型,无论是 bool_constant&lt;false&gt; 或 void 还是其他任何类型,都应该成功替换默认值,因此是首选。在这里,我们说只有当它与默认值匹配时才会发生这种情况。确切的规则是什么?
    • 首先我们默认填充缺失的参数。所以cond&lt;C&gt; -> cond&lt;C, bool_constant&lt;true&gt;&gt;。对于主模板的定义,它包罗万象,因此任何cond&lt;T, U&gt; 都可以使用该定义,但没有必要越专门。 SFINAE 版本更专业,因此一旦正确形成,它优先于主模板(如果匹配)。
    • 好的,最后一句的最后一部分是我一直在寻找的答案:“SFINAE 版本更专业,所以一旦正确形成,它优先于主模板(如果它匹配)”。您可以考虑在回答中强调这一点,因为这是罪魁祸首。我可以阅读任何参考资料吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多