部分模板专业化和icc

Partial Template specialization and icc

本文关键字:icc 专业化      更新时间:2023-10-16

考虑以下代码:

template <class T, class U, class V>
struct Foo { };
template <class T, class U>
struct Foo<T, U, std::integral_constant<int, U::value>> {
  static void print()
  {
    std::cerr << "instantiated";
  }
};
template <class U>
struct Foo<double, U, std::integral_constant<int, U::value>> {
  static void print()
  {
    std::cerr << "instantiated special";
  }
};
struct Bar {
  static const int value = 0;
};
int main(int argc, char ** argv)
{
  using Baz = Foo<double, Bar, std::integral_constant<int, 0>>;
  Baz::print();
  return 0;
}

当我用icc 16.0.1编译它时,我得到以下消息:

main.cpp(38): error: more than one partial specialization matches the template argument list of class "Foo<double, Bar, std::integral_constant<int, 0>>"
            "Foo<T, U, std::integral_constant<int, U::value>>"
            "Foo<double, U, std::integral_constant<int, U::value>>"
    Baz::print();

使用clang 3.7.1和gcc 5.3.0编译(并打印"instanted special")。这是icc中的错误,还是我的代码不正确?对我来说,第二种专业化似乎比第一种更专业化;除了锁定第一个模板参数之外,它与第一个模板相同。

编辑:我应该补充:如果这是icc中的一个错误,有一个好的解决方法吗?

是的,这是ICC中的一个错误。


这两个部分专业化都与您的实现相匹配,因此请深入研究两个合成函数的部分模板排序规则:

template <class T, class U> void f(Foo<T, U, std::integral_constant<int, U::value> ); 
template <class U>          void f(Foo<double, U, std::integral_constant<int, U::value> );

偏序规则包括为每个模板参数合成新的类型,并尝试用每个重载对其余的进行推导。首先,我们尝试用UFoo<_U1, _U2, std::integral_constant<int, _U2::value>>进行推导。由于_U1double不匹配,因此此操作失败。因此,第一次过载至少没有第二次那么专业。接下来,我们试图推导TUFoo<double, _U3, std::integral_constant<int, _U3::value>>的关系。这在CCD_ 8和CCD_。因此,第二个重载至少和第一个重载一样专业化。

因此,第二个过载比第一个过载更加特殊。有一个独特的、最专业的部分偏分,它是应该实例化的(由gcc和clang实例化)。国际商会未能做到这一点是一个错误。