gpt4 book ai didi

c++ - 可变参数模板 : lvalue vs rvalue references

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

以下代码使用 c++11 或更高版本编译

#include <iostream>
#include <cstdlib>
#include <cstdio>

#define p 1

// p1: prototype 1
template <class Function, class... Args>
void addv(Function&& f, Args&... args) {
std::cout << f(args...) << std::endl;
}
// p2: prototype 2
template <class Function, class... Args>
void addv(Function& f, Args&... args) {
std::cout << f(args...) << std::endl;
}

int add(int& a, int& b) {
return a+b;
}

class Adder {
public:
int operator () (int& a, int&b) {
return a+b;
}
};

int main() {
int a = 2;
int b = 1;
Adder adder;

addv<int (int&,int&),int,int>(add,a,b); // uses p1 OR p2
addv<Adder,int,int>(Adder(),a,b); // uses p1
addv<Adder,int,int>(adder,a,b); // uses p2

}

如果原型(prototype) 2 被移除,并且它被编译,则会发生以下错误:
exp.cpp:36:36: error: no matching function for call to ‘addv<Adder, int, int>(Adder&, int&, int&)’
addv<Adder,int,int>(adder,a,b); // uses p2
^
exp.cpp:9:10: note: candidate: template<class Function, class ... Args> void addv(Function&&, Args& ...)
void addv(Function&& f, Args&... args) {
^~~~
exp.cpp:9:10: note: template argument deduction/substitution failed:
exp.cpp:36:36: note: cannot convert ‘adder’ (type ‘Adder’) to type ‘Adder&&’
addv<Adder,int,int>(adder,a,b); // uses p2
^

为什么 adder无法从左值隐式转换为右值,因为需要将行 addv<Adder,int,int>(adder,a,b);使用原型(prototype) 1?

是否可以显式创建 adder 的右值引用?让它正确匹配原型(prototype) 1?

最佳答案

它不能被转换,因为在函数签名中使用右值和左值引用的想法正是为了确保你得到一个或另一个。不是任何一个。

通常使用它是因为如果你得到一个右值,你可以移动它。如果你得到一个左值,你需要复制它。您还可以确保函数只能使用右值或左值调用。

传递函数时,通常的方法是按值获取参数。这也适用于右值和左值。这就是它(几乎总是?)在标准库中完成的方式。函数指针和 Functor 通常复制起来非常便宜。

如果你想要一个可以接受右值和左值的签名,你可以使用 const & .

另请注意,由于 Function&&是一个模板参数,它是一个转发引用。这意味着它将成为右值引用或左值引用,具体取决于您传入的内容。

当您使用显式指定的参数调用函数时

addv<Adder,int,int>(adder,a,b);
^--this

模板参数将准确推导出为 Adder ,然后您的函数将只接受右值,因为签名说 Function&& -> Adder&& .

使代码工作的简单方法是不显式指定模板参数。
addv(adder,a,b);

然后您可以删除原型(prototype) 2,所有函数调用都将起作用。

如果你真的想或者需要指定参数,可以使用 std::move在调用站点将左值转换为右值。
addv<Adder,int,int>(std::move(adder),a,b);

编辑:转换可能有点误导。其实是类型转换。除了值类别外,没有任何变化。

关于c++ - 可变参数模板 : lvalue vs rvalue references,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60936652/

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