【发布时间】:2015-02-13 11:39:45
【问题描述】:
完美转发问题的常见描述表明,我们最好不要使用& 和const& 的组合作为包装函数参数,因为在这种情况下,我们必须编写多个函数来覆盖函数的所有组合论据:
template <typename T1, typename T2>
void wrapper(T1& e1, T2& e2) { func(e1, e2); }
template <typename T1, typename T2>
void wrapper(const T1& e1, T2& e2) { func(e1, e2); }
template <typename T1, typename T2>
void wrapper(T1& e1, const T2& e2) { func(e1, e2); }
template <typename T1, typename T2>
void wrapper(const T1& e1, const T2& e2) { func(e1, e2); }
这是该问题的经典解决方案:
template <typename T1, typename T2>
void wrapper(T1&& e1, T2&& e2) {
func(forward<T1>(e1), forward<T2>(e2));
}
template<class T>
T&& forward(typename std::remove_reference<T>::type& t) noexcept {
return static_cast<T&&>(t);
}
但是为什么我们不能为此目的使用const_cast?我们可以这样写:
template <typename T1, typename T2>
void wrapper(const T1& e1, const T2& e2)
{
T1& e1_ref = const_cast<T1&>(e1);
T2& e2_ref = const_cast<T2&>(e2);
func(e1_ref, e2_ref);
}
通过这种方式,我们不必编写多个函数,并且能够有效地处理左值和右值。那么为什么我们真的需要一个使用引用折叠、模板参数推导和std::forward 的有点棘手的解决方案呢?
【问题讨论】:
-
如果
func被重载并根据其参数是否为 const 做不同的事情怎么办?事实上,如果func不根据其参数的 const-ness 和 value 类别做不同的事情,你为什么还要用完美转发来调用它? -
如果有人真的传递了一个声明为
const的对象呢? -
另外,您的解决方案不保留参数的值类别,即它不会将右值作为右值转发,一切都变成了非常量左值......这是最不完美的转发我'见过。这可以称为糟糕的转发。
-
Advantages of using forward 的可能重复项
-
您基本上是在问“完美转发有什么用?”,隐藏在“如果我不想使用完美转发,我可以做完全不同的事情”的薄纱后面。 :)
标签: c++ c++11 perfect-forwarding const-cast