Nir*_*man 6 c++ templates c++11
请考虑以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
当我使用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();
Run Code Online (Sandbox Code Playgroud)
使用clang 3.7.1和gcc 5.3.0编译(并打印"instantiated 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> );
Run Code Online (Sandbox Code Playgroud)
部分排序规则涉及为每个模板参数合成新类型,并尝试对其余的每个重载进行推导。首先,我们尝试U对进行推论Foo<_U1, _U2, std::integral_constant<int, _U2::value>>。这会失败,因为_U1不匹配double。因此,第一个重载至少不如第二个重载那么专业。接下来,我们尝试推论T和。使用和即可成功。所以第二个重载至少和第一个重载一样专业。UFoo<double, _U3, std::integral_constant<int, _U3::value>>T=doubleU=_U3
因此,第二个重载比第一个重载更加专门。有一种独特的最专业的部分偏化,它应该被实例化(并且由 gcc 和 clang 实例化)。ICC 未能这样做是一个错误。
| 归档时间: |
|
| 查看次数: |
141 次 |
| 最近记录: |