VS2013中std::forward
的实施是
template<class _Ty> inline
_Ty&& forward(typename remove_reference<_Ty>::type& _Arg)
{ // forward an lvalue
return (static_cast<_Ty&&>(_Arg));
}
template<class _Ty> inline
_Ty&& forward(typename remove_reference<_Ty>::type&& _Arg) _NOEXCEPT
{ // forward anything
static_assert(!is_lvalue_reference<_Ty>::value, "bad forward call");
return (static_cast<_Ty&&>(_Arg));
}
左值参考的一个版本,右值参考的一个版本。为什么不对rvalue和左值引用使用通用引用:
template <typename T, typename U>
T&& Forward(U&& arg) {
return static_cast<T&&>(arg);
}
答案 0 :(得分:4)
您的版本不符合标准,因为如果std::forward
是l值引用,则在使用rvalue调用时不需要编译T
。来自[forward]
:
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;
2返回:
static_cast<T&&>(t)
。3如果第二个表单用左值引用类型实例化,则程序格式不正确。
std::forward
以这种方式定义,以确保std::forward
的(某些)误用不会编译。有关更多讨论,请参阅n2951(尽管即使n2951也不使用此确切形式)。
答案 1 :(得分:3)
我正在扩展你在这里指出的问题。
如果您尝试将新创建的右值绑定到l值引用,那么您的版本将引入引用悬空大小写。
当Mankarse链接时,n2951论文引用了这种情况,通过简化它,您可以使用以下代码对其进行总结
#include <iostream>
using namespace std;
template <typename T, typename U>
T&& Forward(U&& arg) {
return static_cast<T&&>(arg);
}
class Container
{
int data_;
public:
explicit Container(int data = 1) // Set the data variable
: data_(data) {}
~Container() {data_ = -1;} // When destructed, first set the data to -1
void test()
{
if (data_ <= 0)
std::cout << "OPS! A is destructed!\n";
else
std::cout << "A = " << data_ << '\n';
}
};
// This class has a reference to the data object
class Reference_To_Container_Wrapper
{
const Container& a_;
public:
explicit Reference_To_Container_Wrapper(const Container& a) : a_(a) {}
// (I) This line causes problems! This "Container" returned will be destroyed and cause troubles!
const Container get() const {return a_;} // Build a new Container out of the reference and return it
};
template <class T>
struct ReferenceContainer
{
T should_be_valid_lvalue_ref;
template <class U> // U = Reference_To_Container_Wrapper
ReferenceContainer(U&& u) :
// We store a l-value reference to a container, but the container is from line (I)
// and thus will soon get destroyed and we'll have a dangling reference
should_be_valid_lvalue_ref(Forward<T>(std::move(u).get())) {}
};
int main() {
Container a(42); // This lives happily with perfect valid data
ReferenceContainer<const Container&> rc( (Reference_To_Container_Wrapper(a)) ); // Parenthesis necessary otherwise most vexing parse will think this is a function pointer..
// rc now has a dangling reference
Container newContainer = rc.should_be_valid_lvalue_ref; // From reference to Container
newContainer.test();
return 0;
}
输出“OPS!A被破坏!”
如果您只是添加“&amp;”在行
const Container& get() const {return a_;}
上述工作正常。