C++中,正确的将LValk转发到函数模板的正确方法是什么?

C++中,正确的将LValk转发到函数模板的正确方法是什么?,c++,c++11,templates,perfect-forwarding,C++,C++11,Templates,Perfect Forwarding,接受参数包以实现完美转发的正确方法是什么,这样它将采用任何类型并简单地转发它们?以下代码适用于常规类型,但在指针类型上失败: template<typename ...A> void b(A &&... args) {} template<typename ...A> void a(A &&... args) { b(std::forward<A>(args)...); } int main() { //

接受参数包以实现完美转发的正确方法是什么,这样它将采用任何类型并简单地转发它们?以下代码适用于常规类型,但在指针类型上失败:

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;
}
[编辑]感谢您的快速回复!我过于简化了——这是我试图解决的问题的一个更接近的例子:

#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;
}
在这种情况下,我没有奢侈让模板自动调整。。。你知道如何做到这一点吗


[编辑2]正如评论中指出的,这与指针无关,我更新了我的示例,只使用左值,您不应该明确指定模板参数;这只会阻止使用模板参数推断,并产生意外的结果

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* &&
编辑

首先,成员函数b和a都不是模板,它们的参数也没有声明为模板

代码不起作用,因为

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)...);
}

不应明确指定模板参数;这只会阻止使用模板参数推断,并产生意外的结果

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* &&
编辑

首先,成员函数b和a都不是模板,它们的参数也没有声明为模板

代码不起作用,因为

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)...);
}

或者,如果坚持使用显式模板参数,则可以编写afoo;。啊,你完全正确。。。但让我更新我的问题,我的实际问题有点复杂,我过于简单:@GaspardP答案修改。谢谢!将成员函数模板设置为其他类型可以使类型顺利转发。或者,如果坚持使用显式模板参数,则可以编写afoo;。啊,你完全正确。。。但让我更新我的问题,我的实际问题有点复杂,我过于简单:@GaspardP答案修改。谢谢!将成员函数模板设置在不同的类型上可以使类型顺利地转发。但这不是一个公平的比较。一个更公平的是int bar=5;abar-同样的错误,不是关于指针。你是对的,我没有意识到这是关于左值的,与指针无关,即使在我的新示例中,它也不一定是指针。谢谢你强调这一点!现在,fun::a只接受右值参数。此外,它不是一个功能模板,因此,完美的转发将不起作用。如果你想转发它的参数,写一些东西作为模板-&&。。。args{bstd::forwardargs…;};。但这不是一个公平的比较。一个更公平的是int bar=5;abar-同样的错误,不是关于指针。你是对的,我没有意识到这是关于左值的,与指针无关,即使在我的新示例中,它也不一定是指针。谢谢你强调这一点!现在,fun::a只接受右值参数。此外,它不是一个功能模板,因此,完美的转发将不起作用。如果你想转发它的参数,写一些东西作为模板-&&。。。args{bstd::forwardargs…;};。