VC 错误,带有声明和通用引用或未定义的行为

VC++ Bug with Decltype and Universal Reference or Undefined Behavior?

本文关键字:引用 未定义 错误 声明 VC      更新时间:2023-10-16

我有此代码:

#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;
}

使用VC 2015编译时,我得到了此错误:

error C2893: Failed to specialize function template 'T f2(T &&)'

主要问题是在表达式f2(rr)上使用decltype()。请注意,f2的参数为T&&。这是Scott Meyers:Universal Reference的通用参考。我期望f2(rr)会产生一种表达式,其类型是函数参考。在GCC中,它正常运行并返回真实,因此确认f2(rr)是函数参考。

这仅仅是一个带有VC 2015的错误,而不是与函数名称一起使用的Univeral引用时不确定的行为?

编辑:这在VC 2015中正确起作用:

int main()
{
  cout << f2(rr)(10) <<endl;
}

结果:

400

通用引用是可以将模板参数推导为参考类型的特殊上下文。假设我们有

template <typename T> auto f(T &&) -> T;
int i;
int g(int);

f(i)T推论为 int &,以形成 auto f<int &>(int &) -> int &
f(std::move(i))T推论为int以形式auto f<int>(int &&) -> int

发生这种情况的规则以:

14.8.2.1从函数调用[temp.deduct.call]

从函数调用[temp.deduct.call]推论模板参数

3 [...]如果P是对CV UNQUALIFIED模板参数的RVALUE引用,并且该参数为lvalue,则" type" type'lvalue引用了A&quot&quord&quort'用于代替A进行类型扣除。[...]

问题是,当调用f(g)时,g是lvalue吗?

提出问题甚至有意义吗?如果T是函数类型,则T &T &&都可以使用std::move来创建对命名函数的引用。功能不存在lvalue/rvalue区别。

任意地,C 标准说是的,g是一个LVALUE。功能类型的表达式永远不会是RVALUE(无论是XVALUES还是PRVALUES)。可以产生对功能类型的rvalue引用的类型,但是即使到那时,它们所形成的表达式也是lvalues。标准中其他地方还有更多的明确陈述,但它们源于:

3.10 lvalues and rvalues [basic.lval]

(1.1) - lvalue [...]指定函数或对象。[...]

(1.2) - xvalue [...]也指一个对象,[...]

(1.4) - rvalue [...]是xvalue,临时对象(12.2)或subobject,或与对象无关的值。

(注意:g都不是"值得",因此上一部分不适用。" value"在[basic..types] p4中定义,并且适用于琐碎的可复制类型,哪些功能类型不是。)

由于g是LVALUE,因此T应将其推定为int(&)(int),这是VC 中的错误。

虽然很微妙。