在 C++ 中,将左值完美转发到函数模板的正确方法是什么?
In C++, what is the correct way to do perfect forwarding an lvalue to a function template?
接受完美转发参数包的正确方法是什么,这样它可以接受任何类型并简单地转发它们?以下代码适用于常规类型,但适用于指针类型:
template<typename ...A>
void b(A &&... args)
{}
template<typename ...A>
void a(A &&... args)
{
b(std::forward<A>(args)...);
}
int main() {
// ok
a<int>(5);
// error: cannot bind rvalue reference of type ‘int*&&’ to lvalue of type ‘int*’
int *foo = nullptr;
a<int*>(foo);
return 0;
}
[edit] 感谢您的快速回复!我过于简单化了——这是我试图解决的问题的一个更接近的例子:
#include <iostream>
using namespace std;
template<typename F>
struct fun;
template<typename F, typename ...A>
struct fun<F(A...)>
{
void b(A &&... args)
{}
void a(A &&... args)
{
b(std::forward<A>(args)...);
}
};
int main() {
// ok
fun<void(int)> f1;
f1.a(5);
// error: cannot bind 'int' lvalue to 'int&&'
fun<void(int)> f2;
int x = 5;
f2.a(x);
return 0;
}
在这种情况下,我无法让模板自动调整...知道如何实现吗?
[edit 2] 正如评论中指出的,这与指针无关,我更新了示例以简单地使用 lvalue
您不应显式指定模板参数;这只是防止模板参数推导与 forwarding reference 一起使用,并产生意外结果。
a<int>(5); // A is specified as int then function parameter's type is int&&.
// 5 is an rvalue and could be bound to int&&
a<int*>(foo); // A is specified as int* then function parameter's type is int* &&.
// foo is an lvalue and couldn't be bound to int* &&
刚刚
a(5); // 5 is rvalue, then A is deduced as int and function parameter's type collapses to int&&
int *foo = nullptr;
a(foo); // foo is lvalue, then A is deduced as int* & and function parameter's type collapses to int* &
编辑
首先,成员函数b
和a
都不是模板,它们的参数根本没有声明为forwarding reference。
代码无效,因为
fun<void(int)> f2;
int x = 5;
f2.a(x); // A is specified as int then function parameter's type is int &&.
// x is an lvalue and couldn't be bound to int &&
我不确定你的意图,你可以将其更改为
fun<void(int&)> f2;
// ^
int x = 5;
f2.a(x); // A is specified as int& then function parameter's type collapses to int&.
// x is an lvalue and could be bound to int&
或者使它们成为函数模板并仍然应用转发引用。
template <typename... T>
void b(T &&... args)
{}
template <typename... T>
void a(T &&... args)
{
b(std::forward<T>(args)...);
}
接受完美转发参数包的正确方法是什么,这样它可以接受任何类型并简单地转发它们?以下代码适用于常规类型,但适用于指针类型:
template<typename ...A>
void b(A &&... args)
{}
template<typename ...A>
void a(A &&... args)
{
b(std::forward<A>(args)...);
}
int main() {
// ok
a<int>(5);
// error: cannot bind rvalue reference of type ‘int*&&’ to lvalue of type ‘int*’
int *foo = nullptr;
a<int*>(foo);
return 0;
}
[edit] 感谢您的快速回复!我过于简单化了——这是我试图解决的问题的一个更接近的例子:
#include <iostream>
using namespace std;
template<typename F>
struct fun;
template<typename F, typename ...A>
struct fun<F(A...)>
{
void b(A &&... args)
{}
void a(A &&... args)
{
b(std::forward<A>(args)...);
}
};
int main() {
// ok
fun<void(int)> f1;
f1.a(5);
// error: cannot bind 'int' lvalue to 'int&&'
fun<void(int)> f2;
int x = 5;
f2.a(x);
return 0;
}
在这种情况下,我无法让模板自动调整...知道如何实现吗?
[edit 2] 正如评论中指出的,这与指针无关,我更新了示例以简单地使用 lvalue
您不应显式指定模板参数;这只是防止模板参数推导与 forwarding reference 一起使用,并产生意外结果。
a<int>(5); // A is specified as int then function parameter's type is int&&.
// 5 is an rvalue and could be bound to int&&
a<int*>(foo); // A is specified as int* then function parameter's type is int* &&.
// foo is an lvalue and couldn't be bound to int* &&
刚刚
a(5); // 5 is rvalue, then A is deduced as int and function parameter's type collapses to int&&
int *foo = nullptr;
a(foo); // foo is lvalue, then A is deduced as int* & and function parameter's type collapses to int* &
编辑
首先,成员函数b
和a
都不是模板,它们的参数根本没有声明为forwarding reference。
代码无效,因为
fun<void(int)> f2;
int x = 5;
f2.a(x); // A is specified as int then function parameter's type is int &&.
// x is an lvalue and couldn't be bound to int &&
我不确定你的意图,你可以将其更改为
fun<void(int&)> f2;
// ^
int x = 5;
f2.a(x); // A is specified as int& then function parameter's type collapses to int&.
// x is an lvalue and could be bound to int&
或者使它们成为函数模板并仍然应用转发引用。
template <typename... T>
void b(T &&... args)
{}
template <typename... T>
void a(T &&... args)
{
b(std::forward<T>(args)...);
}