gpt4 book ai didi

c++ - 为什么此重载分辨率选择带有右值引用的签名?

转载 作者:行者123 更新时间:2023-12-02 10:10:01 27 4
gpt4 key购买 nike

下面的程序使用带有右值引用签名的append_list函数,而不是const引用签名。为什么?

#include <stdio.h>

#include <iterator>
#include <memory>
#include <vector>

class foo {
public:
std::vector<int> bar{1};
};

template<typename T, typename U>
static void append_list(T &t, const U &u) {
t.insert(t.end(), u.begin(), u.end());
}

template<typename T, typename U>
static void append_list(T &t, U &&u) {
printf("move\n");
std::move(u.begin(), u.end(), std::back_inserter(t));
}

int main() {
auto shmoo = std::make_shared<foo>();
std::vector<int> baz{2};
append_list(baz, shmoo->bar);
}
https://godbolt.org/z/jdbEd1
AFAICS shmoo->bar应该是对 shmoo对象的bar字段的左值引用。我在这里看不到“转换序列”来进行右值引用,但是我承认这里有很多我不理解的事情。

最佳答案

在您的示例代码中,U是转发引用,而不是RValue引用:

template<typename T, typename U>
static void append_list(T &t, U &&u) {
// ^~~~~
转发引用的行为与通常的模板推断类型不同,因为 U将成为其输入的 精确类型,与CV限定词和值类别都匹配。
  • 对于T类型的PR值,这将生成U = T
  • 对于T类型的X值,这将生成U = T&&
  • 对于T类型的L值,这将生成U = T&

  • 这不同于正常模板匹配,后者从 const U&推导的类型将确定 U = T
    当作为带有函数模板的过载模板(通过模板匹配来推导其参数)呈现时,转发引用实际上将是“贪婪的”-因为在大多数情况下,它的 无疑会更好地匹配以解决过载。

    用您的示例代码:
    int main() {
    auto shmoo = std::make_shared<foo>();
    std::vector<int> baz{2};
    append_list(baz, shmoo->bar);
    }
    schmoo->barconst的非 std::vector<int>左值引用传递给 append_list
    在重载解析期间,编译器将始终以最匹配的方式解析该函数​​(即,所需的转换次数最少)。在上述重载中, std::vector<int>&可以与 const U& = const std::vector<T>&匹配-但这需要添加 const,而不是完全匹配的 U&& = std::vector&`。
    结果,调用了前向引用重载。

    关于c++ - 为什么此重载分辨率选择带有右值引用的签名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64051598/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com