【问题标题】:Partial Template specialization and icc部分模板专业化和 icc
【发布时间】:2016-05-13 17:40: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 编译(并打印“实例化特殊”)。这是 icc 中的错误,还是我的代码不正确?对我来说,第二个专业化似乎比第一个专业化更加专业化。除了锁定第一个模板参数之外,它与第一个相同。

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

【问题讨论】:

  • 在我看来确实像 icc 中的一个错误。
  • 您能否检查comments below 中的建议是否解决了ICC 上的问题?当然,这并不能完全解决您的问题,只是在调查中向前迈出了一步。
  • 在实际代码中,整数来自U的嵌套成员,这反过来又给clang带来了问题,所以我的同事从非类型转换为类型模板参数。

标签: c++ templates c++11


【解决方案1】:

是的,这是 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> );

部分排序规则涉及为每个模板参数合成新类型,并尝试对每个重载对其余的进行推导。首先,我们尝试从Foo&lt;_U1, _U2, std::integral_constant&lt;int, _U2::value&gt;&gt; 中推断出U。这失败了,因为_U1 与double 不匹配。所以第一个重载至少不像第二个那么专业。接下来,我们尝试对Foo&lt;double, _U3, std::integral_constant&lt;int, _U3::value&gt;&gt; 推导出T 和U。这通过T=double 和U=_U3 成功。所以第二个重载至少和第一个一样专精。

因此,第二个重载比第一个更专业。有一个独特的最专业的部分偏化,它应该被实例化(并且是由 gcc 和 clang)。 ICC 未能这样做是一个错误。

【讨论】:

  • 部分排序和非推导上下文再次起作用...用推导的int I 替换U::value 很可能会使事情按预期工作。看起来 EDG 前端(这里最有可能由 ICC 使用)与 MSVC 一致,并且由于未推断上下文,两者都没有至少像另一个那样专业化。令人担忧的是,我在--strict 模式下测试了一个非 MSVC 怪癖的 EDG,它仍然做同样的事情。随着编译器的发展,它是 2 对 2。太好了。
  • @bogdan 为什么会导致扣减失败?
  • 我同意你解释的第二步推论失败是没有意义的。我只是指出非推断的上下文很可能是问题的原因(我对 EDG 的行为感到非常惊讶)。我会要求 OP 检查将 U::value 更改为 0(或如上所述)是否可以解决 ICC 上的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多