当从函数返回为"const"时,为什么原始类型和用户定义类型的行为不同?

xml*_*lmx 41 c++ standards overloading overload-resolution c++11

#include <iostream>

using namespace std;

template<typename T>
void f(T&&) { cout << "f(T&&)" << endl; }

template<typename T>
void f(const T&&) { cout << "f(const T&&)" << endl; }

struct A {};
const A g1() { return {}; }
const int g2() { return {}; }

int main()
{
    f(g1()); // outputs "f(const T&&)" as expected.
    f(g2()); // outputs "f(T&&)" not as expected.
}
Run Code Online (Sandbox Code Playgroud)

问题描述嵌入在代码中.我的编译器是clang 5.0.

我只是好奇:

在这种情况下,为什么C++会以不同方式处理内置类型和自定义类型?

Wea*_*ish 29

我没有标准的引用,但是cppreference证实了我的怀疑:

非类非数组prvalue不能是cv限定的.(注意:函数调用或强制转换表达式可能会导致非类cv限定类型的prvalue,但会立即删除cv-qualifier.)

返回const int只是一个普通的intprvalue,并使非const重载比一个更好const.

  • @alfC因为`const A`意味着'A`的所有成员都不能被改变(即使你复制A),而int甚至不存在成员. (3认同)
  • 这就留下了为什么C++允许类prvalues被cv限定的问题.Imho,这对于允许非阶级prvalues而言同样缺乏意义. (3认同)

Pav*_*l P 22

当从函数返回为"const"时,为什么原始类型和用户定义类型的行为不同?

因为const从函数返回的基本类型中删除了部分.原因如下:

C++ 11§ 5 Expressions [expr](第84页):

8

每当glvalue表达式作为操作符的操作数出现时,该操作符需要该操作数的prvalue,左值到右值(4.1),数组到指针(4.2)或函数到指针(4.3)标准转换是用于将表达式转换为prvalue.[注意:因为当表达式转换为prvalue时,cv-quali firs被从非类型表达式的类型中删除,例如,类型为const int的左值表达式可以在类型为int的prvalue表达式中使用是必须的. - 尾注]

同样来自§ 5.2.3 Explicit type conversion (functional notation) [expr.type.conv](第95页):

2

表达式T(),其中T是非数组完整对象类型或(可能是cv-quali fi ed)void类型的简单类型指定者或typename-speci fi er,它创建了一个特定类型的prvalue,它是有价值的( 8.5;没有对void()情况进行初始化).[注意:如果T是具有cv-quali fi ed的非类型类型,则在确定结果prvalue(3.10)的类型时将忽略cv-quali firs. - 尾注]

这意味着返回的const int prvalueg2()被有效地视为int.


son*_*yao 13

标准引用,

§8/ 6表达式[expr]

如果prvalue最初具有类型"cv T",其中T是cv非限定的非类非数组类型,则在进行任何进一步分析之前将表达式的类型调整为T.

§8/ 9表达式[expr]

(强调我的)

每当glvalue表达式作为操作符的操作数出现,该操作符需要该操作数的prvalue时,将应用左值到右值,数组到指针或函数到指针的标准转换来将表达式转换为prvalue.[注意:因为当表达式转换为prvalue时,cv-qualifiers从非类型表达式的类型中删除,所以const int例如,可以在int需要类型的prvalue表达式的情况下使用类型的左值表达式. - 结束说明]

因此,对于g2(),int是一种非类类型,和(返回值)g2()是一个prvalue表达,则const限定符被去除,因此,返回类型不是const int,而是int.这就是为什么f(T&&)叫.

  • 规范性措辞见[\ [expr \]/6](http://eel.is/c++draft/expr#6). (4认同)