C++ l值ref、r值ref和非ref类型的完美转发可变模板?

C++ l值ref、r值ref和非ref类型的完美转发可变模板?,c++,c++14,variadic-templates,rvalue-reference,forwarding-reference,C++,C++14,Variadic Templates,Rvalue Reference,Forwarding Reference,在我的程序中,我有一些模板类,它们主要是一个特殊用途std::函数的包装器。最简单的例子是: template <typename... Args> class Foo { public: explicit Foo(std::function<void(Args&&...)> _function) : function_(_function) {} template<

在我的程序中,我有一些模板类,它们主要是一个特殊用途std::函数的包装器。最简单的例子是:

template <typename... Args>
class Foo {

    public:

        explicit Foo(std::function<void(Args&&...)> _function)
            : function_(_function)
        {}

        template<typename... Arguments>
        void Bar(Arguments&&... _args) {
            function_(std::forward<Arguments>(_args)...);
        }

    private:

        std::function<void(Args&&...)> function_;

};
模板
福班{
公众:
显式Foo(std::function\u函数)
:函数(函数)
{}
模板
无效栏(参数&&…\参数){
函数(std::forward(_args)…);
}
私人:
std::函数;
};
这些模板的实例化通常是l值引用、r值引用或无引用类型的组合。问题是,当某些参数是非引用类型(如int或std::vector)时,调用Bar-leed会导致错误。解决方法是声明一个临时变量,然后将其移动到函数调用中

int main(){
    Foo<int> test1([](int x) { });
    const int x = 1;
    test1.Bar(x); // [Error] cannot bind rvalue reference of type 'int&&' to lvalue of type 'const int'

    int tmp = x;
    test1.Bar(tmp); // [Error] cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
    test1.Bar(std::move(tmp)); // [OK] But I don't want to have to reassign and move every time I use this.

    /* I want perfect forwarding on variables that can be forwarded. */
    /* There are cases when the templates are like this with a combination of l-value ref and r-value ref and non-ref types. */
    Foo<const std::vector<uint8_t>&, std::vector<uint8_t>&&, int> test2([](const std::vector<uint8_t>&, std::vector<uint8_t>&&, int) { });
    test2.Bar(std::vector<uint8_t>(1, 2), std::vector<uint8_t>(1, 2), x); // [Error] cannot bind rvalue reference of type 'int&&' to lvalue of type 'const int'

    return 1;
}
intmain(){
footest1([](intx){});
常数int x=1;
test1.Bar(x);//[Error]无法将“int&”类型的右值引用绑定到“const int”类型的左值
int tmp=x;
test1.Bar(tmp);//[Error]无法将“int&”类型的右值引用绑定到“int”类型的左值
test1.Bar(std::move(tmp));//[OK]但我不想每次使用它时都要重新分配和移动。
/*我想完美的转发变量,可以转发*/
/*在有些情况下,模板是l值ref和r值ref以及非ref类型的组合*/
Foo test2([](const std::vector&,std::vector&&,int){});
test2.Bar(std::vector(1,2),std::vector(1,2),x);//[Error]无法将'int&'类型的右值引用绑定到'const int'类型的左值
返回1;
}
我希望能够将Bar与任何模板参数一起使用,而不必每次都重新分配和std::move(),而且还可以完美地转发ref参数。有办法做到这一点吗

编辑 在浏览了一下web之后,问题是
std::function\
不是一个接受通用ref的函数,而是一个r-val ref。因此,尝试转发无ref类型会抛出错误

那么问题是,是否有可能拥有并存储一个接受通用引用的std::函数

std::function
中,您实际上期望r值引用,您可能希望
std::function

template <typename F>
class Foo {
public:
    explicit Foo(F f) : f(f) {}

    template <typename... Ts>
    auto operator ()(Ts&&... args) const
    -> decltype(f(std::forward<Ts>(args)...))
    {
        return f(std::forward<Ts>(args)...);
    }

private:
    F f;
};

template <typename F>
Foo<F> MakeFoo(F f) { return Foo<F>{f}; }

std::function
中,您实际上期望r值引用,您可能想要
std::function

template <typename F>
class Foo {
public:
    explicit Foo(F f) : f(f) {}

    template <typename... Ts>
    auto operator ()(Ts&&... args) const
    -> decltype(f(std::forward<Ts>(args)...))
    {
        return f(std::forward<Ts>(args)...);
    }

private:
    F f;
};

template <typename F>
Foo<F> MakeFoo(F f) { return Foo<F>{f}; }

也许这会有所帮助:请注意,在您的情况下,
void Bar(…)
没有使用universalreference@Amadeus哎呀!我的MWE不好。将其更改为通用参考(错误相同)。我现在将查看该链接,看看它是否有用。不,不可能存储接受通用引用的
std::function
。只有函数模板可以采用通用引用,但
std::function::operator()
不是模板。这可能会有所帮助:请注意,在您的情况下,
void Bar(…)
没有使用通用引用reference@Amadeus哎呀!我的MWE不好。将其更改为通用参考(错误相同)。我现在将查看该链接,看看它是否有用。不,不可能存储接受通用引用的
std::function
。只有函数模板可以采用通用引用,但
std::function::operator()
不是模板。