VS 2013 无法根据模板参数使用通用引用和 return 类型专门化函数模板
VS 2013 fails to specialize function template with universal reference and return type depending on template parameter
VS 2013 说它不能特化以下代码中的函数模板:
struct W { };
template <class T>
typename T::result_type
f (const W & w, T && t) {
return 0;
}
/* ... */
struct V { typedef int result_type; };
W w {};
V v {};
f (w, v);
如果我用 int
替换 typename T::result_type
或者如果我用 T&
替换通用参考 T&&
,它不会抱怨。
在我看来,上面的代码是正确的。这是编译器错误,还是我做错了什么?
编译器是对的。转发引用 (1) 的工作方式是,如果传递了类型 U
的左值,它们使用 U&
而不是 U
进行类型推导。由于 v
在您的情况下是一个左值,因此 T
被推断为 V&
。 V&
是引用类型,它没有嵌套类型(甚至不能有)。
使用转发引用时,您必须始终使用 std::remove_reference
获取基础类型:
template <class T>
typename std::remove_reference<T>::type::result_type
f (const W & w, T && t) {
return 0;
}
(1) 自 CppCon 2014 以来,"forwarding reference" 被接受为 "universal reference," 的替代术语,因为它更好地捕捉了意图。
VS 2013 说它不能特化以下代码中的函数模板:
struct W { };
template <class T>
typename T::result_type
f (const W & w, T && t) {
return 0;
}
/* ... */
struct V { typedef int result_type; };
W w {};
V v {};
f (w, v);
如果我用 int
替换 typename T::result_type
或者如果我用 T&
替换通用参考 T&&
,它不会抱怨。
在我看来,上面的代码是正确的。这是编译器错误,还是我做错了什么?
编译器是对的。转发引用 (1) 的工作方式是,如果传递了类型 U
的左值,它们使用 U&
而不是 U
进行类型推导。由于 v
在您的情况下是一个左值,因此 T
被推断为 V&
。 V&
是引用类型,它没有嵌套类型(甚至不能有)。
使用转发引用时,您必须始终使用 std::remove_reference
获取基础类型:
template <class T>
typename std::remove_reference<T>::type::result_type
f (const W & w, T && t) {
return 0;
}
(1) 自 CppCon 2014 以来,"forwarding reference" 被接受为 "universal reference," 的替代术语,因为它更好地捕捉了意图。