Forwarding the const-ness of a template parameter, should I use a forwarding reference?

c++, c++11, constants, forwarding-reference, templates

Solution

Yes, a forwarding reference is the right way, and if it calms you, you can certainly forward the parameter:

template <typename T> void foo(T&& x){
    std::forward<T>(x)();
}

Now it even works with ref-qualified call operators.

Problem

I want to write a function `foo` that should call `operator()` of its parameter, as illustrated in the (broken) code below: ``` 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{}); } ``` Obviously the code doesn't work, because `operator()` is non-`const`, but `foo()` requires its parameter to be `const`. As a template function, `foo()` should work with both `const` and non-`const` functors, and not be picky about the `const`-ness of its argument. If I change `foo()` by removing the `const` to the following: ``` template <typename T> void foo(T& x) { /* ... */ } ``` ... it also won't work because you can't convert an rvalue reference to a non-`const` lvalue reference, so `foo(MyFunctor{})` cannot be called. Changing `foo()` to a forwarding reference resolves all the problems: ``` template <typename T> void foo(T&& x) { /* ... */ } ``` But is this the "right" way? Shouldn't forwarding references be used only with `std::forward()` (i.e. the parameter shouldn't be touched apart from forwarding it to another function)?

Original source