【问题标题】:Default template paramters and partial specialization默认模板参数和部分特化
【发布时间】:2020-05-03 07:44:41
【问题描述】:

我正在尝试使用默认参数来理解部分模板专业化。如果我在 is_comparable 专业化中删除强制转换为 void,则打印的值始终为 false,而如果我保持强制转换为 (void),则一切正常。有人可以解释为什么需要演员表作废吗?它可能与匹配 T3 的默认模板参数有关,但我试图在这里对模板部分专业化和默认模板参数的注意事项进行一些额外的了解。

template<typename T1, typename T2, typename T3 = void>
struct is_comparable
{
 static const bool value = false;
};

template<typename T1, typename T2>
struct is_comparable<T1, T2, decltype((void)(std::declval<T1>() == std::declval<T2>()))>
{
  static const bool value = true;
};

int main()
{
   cout << boolalpha;
   cout << is_comparable<int, char>::value << endl;
   cout << is_comparable<int, float *>::value << endl;
}

更新:即使使用指针,我也观察到相同的行为。我会假设在这种情况下会选择部分专业化?

template<typename T1, typename T2, typename T3 = void>
struct is_comparable
{
 static const bool value = false;
};

template<typename T1, typename T2>
struct is_comparable<T1*, T2*, decltype((std::declval<T1>() == std::declval<T2>()))>
{
  static const bool value = true;
};

int main()
{
   cout << boolalpha;
   cout << is_comparable<int*, int*>::value << endl;
}

【问题讨论】:

    标签: c++ templates decltype enable-if


    【解决方案1】:

    我们默认使用主模板,所以

    • is_comparable&lt;int, char&gt;is_comparable&lt;int, char, void&gt;
    • is_comparable&lt;int, float *&gt;is_comparable&lt;int, float*, void&gt;
    • is_comparable&lt;int*, int*&gt;is_comparable&lt;int*, int*, void&gt;

    现在,您没有 void cast 的专业化主要是(除非operator== 的特殊重载)是

    • is_comparable&lt;T1, T2, bool /* with SFINAE */&gt;

    因此与预期的参数不匹配。 你必须使用:

    • is_comparable&lt;int, char, bool&gt;
    • is_comparable&lt;int, float *, bool&gt;
    • is_comparable&lt;int*, int*, bool&gt;

    另一种转换为void 的方法是std::void_t

    template<typename T1, typename T2, typename Enabler = void>
    struct is_comparable : std::false_type {};
    
    template<typename T1, typename T2>
    struct is_comparable<T1, T2,
                         std::void_t<decltype(std::declval<T1>() == std::declval<T2>())>>
        : std::true_type {};
    

    【讨论】:

      【解决方案2】:

      编译器实例化主模板并获得以下信息:

      is_comparable<int, char, void>
      

      然后,为了选择最佳匹配,它会尝试实例化您的特化(假设没有类型转换 void 并假设类型替换成功)并获取以下类型:

      is_comparable<int, char, bool>
      

      它根本不匹配主模板,所以它不可能是更好的匹配。

      【讨论】:

      • 谢谢伊戈尔。我已经更新了我的问题以包含同一问题的不同情况,即当两个模板参数都是 int* 时。在这种情况下,我会假设选择专业化,但即使在这种情况下,也会选择主模板。
      • 从添加更多调试信息来看,它看起来仍然更喜欢 is_comparable [with T1 = int; T2 = 整数*;当第三个模板参数是 boolvoid 时,T3 = void]* 超过特化
      • @user3882729 再次,is_comparable&lt;int*, char*, bool&gt;is_comparable&lt;int*, int*, void&gt; 不同,所以不考虑!为了更好地匹配,您的专业化应该匹配主模板!因此,要么将bool 设置为主模板中的默认参数,要么将此参数设置为void 在专业化中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多