转发模板参数的常量,我应该使用转发引用吗?

Ber*_*ard 5 c++ templates const c++11 forwarding-reference

我想编写一个foo应该调用operator()其参数的函数,如下面(破碎)代码所示:

template <typename T> void foo(const T& x){
    x();
}

struct MyFunctor{
    int data;
    void operator()(){
        /* stuff that might modify the data */
    }
};

int main()
{
    foo(MyFunctor{});
}
Run Code Online (Sandbox Code Playgroud)

显然代码不起作用,因为operator()它是非的const,但foo()需要它的参数const.

作为模板函数,foo()应该使用两个const和非const函子,并且不要挑剔const它的参数的性质.

如果我foo()通过删除const以下内容进行更改:

template <typename T> void foo(T& x) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

...它也不起作用,因为你无法将右值引用转换为非const左值引用,因此foo(MyFunctor{})无法调用.

更改foo()为转发引用可解决所有问题:

template <typename T> void foo(T&& x) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

但这是"正确的"方式吗?不应该仅使用转发引用std::forward()(即,除了将参数转发给另一个函数之外,不应该触及该参数)?

Ker*_* SB 4

是的,转发引用是正确的方法,如果它能让你平静下来,你当然可以转发参数:

template <typename T> void foo(T&& x){
    std::forward<T>(x)();
}
Run Code Online (Sandbox Code Playgroud)

现在它甚至可以与 ref 限定的调用运算符一起使用。