C++ VC++;具有Decltype和通用引用或未定义行为的Bug?
我有以下代码:C++ VC++;具有Decltype和通用引用或未定义行为的Bug?,c++,c++11,decltype,compiler-bug,C++,C++11,Decltype,Compiler Bug,我有以下代码: #include <iostream> #include <type_traits> using namespace std; template<typename T> T f2(T&&t) { return t; } int rr(int i) { return 40*i; } int main() { cout << is_function< remove_reference<de
#include <iostream>
#include <type_traits>
using namespace std;
template<typename T>
T f2(T&&t) {
return t;
}
int rr(int i) {
return 40*i;
}
int main()
{
cout << is_function< remove_reference<decltype(f2(rr))>::type>::value << endl;
}
主要问题是在表达式f2(rr)
上使用decltype()
。请注意,f2
的参数是T&
。这被Scott Meyers称为通用参考。我希望f2(rr)
生成一个类型为函数引用的表达式。在GCC中,它正常运行并返回true,因此确认f2(rr)
是一个函数引用
当univeral引用与函数名一起使用时,这仅仅是VC++2015的一个bug,而不是未定义的行为吗
编辑:这在VC++2015中正常工作:
int main()
{
cout << f2(rr)(10) <<endl;
}
通用引用是一种特殊的上下文,在此上下文中可以将模板参数推断为引用类型。假设我们有
template <typename T> auto f(T &&) -> T;
int i;
int g(int);
模板自动f(T&)->T;
int i;
int g(int);
f(i)
将T
推断为int&
形成autof(int&)->int&
f(std::move(i))
将T
推断为int
以形成自动f(int&)->int
发生这种情况时的规则如下所示:
14.8.2.1从函数调用中推断模板参数[temp.Decrete.call]
3[…]如果p
是对cv非限定模板参数的右值引用,且参数是左值,则类型推断使用“对a
的左值引用”代替a
。[……]
问题是,当调用f(g)
时,g
是左值吗
问这个问题有意义吗?如果T
是一种函数类型,那么T&
和T&
都可以用于创建对命名函数的引用,而不需要std::move
。函数不存在左值/右值的区别
任意,C++标准称是,<代码> g <代码>是一个LValk。函数类型的表达式从不为右值(无论是xvalues还是prvalues)。可以生成对函数类型的右值引用的类型,但即使如此,它们形成的表达式也是左值。本标准的其他地方有更明确的陈述,但它们如下所示:
3.10左值和右值[basic.lval] (1.1)--左值[…]表示函数或对象。[……] (1.2)--xvalue[…]也指对象[…] (1.4)--右值[…]是一个xvalue、一个临时对象(12.2)或其子对象,或者是一个与对象无关的值 (注意:g
也不是“值”,因此最后一部分不适用。“值”在[basic.types]p4中定义,并适用于可复制的普通类型,而函数类型不适用。)
由于
g
是一个左值,T
应该被推断为int(&)(int)
,这是VC++中的一个错误。不过这是一个相当微妙的问题。通用引用是一种特殊的上下文,在这种上下文中,模板参数可以推断为引用类型。假设我们有
template <typename T> auto f(T &&) -> T;
int i;
int g(int);
模板自动f(T&)->T;
int i;
int g(int);
f(i)
将T
推断为int&
形成autof(int&)->int&
f(std::move(i))
将T
推断为int
以形成自动f(int&)->int
发生这种情况时的规则如下所示:
14.8.2.1从函数调用中推断模板参数[temp.Decrete.call]
3[…]如果p
是对cv非限定模板参数的右值引用,且参数是左值,则类型推断使用“对a
的左值引用”代替a
。[……]
问题是,当调用f(g)
时,g
是左值吗
问这个问题有意义吗?如果T
是一种函数类型,那么T&
和T&
都可以用于创建对命名函数的引用,而不需要std::move
。函数不存在左值/右值的区别
任意,C++标准称是,<代码> g <代码>是一个LValk。函数类型的表达式从不为右值(无论是xvalues还是prvalues)。可以生成对函数类型的右值引用的类型,但即使如此,它们形成的表达式也是左值。本标准的其他地方有更明确的陈述,但它们如下所示:
3.10左值和右值[basic.lval] (1.1)--左值[…]表示函数或对象。[……] (1.2)--xvalue[…]也指对象[…] (1.4)--右值[…]是一个xvalue、一个临时对象(12.2)或其子对象,或者是一个与对象无关的值 (注意:g
也不是“值”,因此最后一部分不适用。“值”在[basic.types]p4中定义,并适用于可复制的普通类型,而函数类型不适用。)
由于
g
是一个左值,T
应该被推断为int(&)(int)
,这是VC++中的一个错误。这是一个相当微妙的问题。VC++似乎将T
推断为int(int)
,它用于将函数传递给T&
类型的参数,但使T
成为无效的函数返回类型。GCC将T
推断为int(&)(int)
。编译器应该是正确的。在CLAN上编译好。上个月从微软Connect得到了这个响应:“谢谢报告这个问题。这个问题的解决已经被检查到编译器源。修复应该在VisualC++的未来版本中显示。”因此,这是VC++2015中的一个bug,已经修复,可能会在VC++2017年发布,或者2015年的service pack VC++似乎将T
推断为int(int)
,这是
template <typename T> auto f(T &&) -> T;
int i;
int g(int);