【发布时间】:2010-10-27 13:49:15
【问题描述】:
鉴于GMan's 美味邪恶auto_cast 实用函数炮制here,我一直试图弄清楚为什么当我试图从右值auto_cast 时它不能为我编译(在MSVC 上10.0)。
这是我正在使用的代码:
template <typename T>
class auto_cast_wrapper : boost::noncopyable
{
public:
template <typename R>
friend auto_cast_wrapper<R> auto_cast(R&& pX);
template <typename U>
operator U() const
{
return static_cast<U>( std::forward<T>(mX) );
}
private:
//error C2440: 'initializing': cannot convert from 'float' to 'float &&'
auto_cast_wrapper(T&& pX) : mX(pX) { }
T&& mX;
};
template <typename R>
auto_cast_wrapper<R> auto_cast(R&& pX)
{
return auto_cast_wrapper<R>( std::forward<R>(pX) );
}
int main()
{
int c = auto_cast( 5.0f ); // from an rvalue
}
尽我所能,我尝试遵循 C++0x 引用折叠规则和here 概述的模板参数推导规则,据我所知,上面给出的代码应该可以工作。
回想一下,在 0x 之前的 C++ 中,不允许对引用进行引用:像 A& & 之类的东西会导致编译错误。相比之下,C++0x 引入了以下引用折叠规则:
- A&&变成A&
- A& && 变成 A&
- A&& & 变成 A&
- A&& && 变为 A&&
第二条规则是一个特殊的模板参数推导规则,用于通过对模板参数的右值引用获取参数的函数模板:
template<typename T> void foo(T&&);这里适用以下规则:
- 当在 A 类型的左值上调用 foo 时,T 解析为 A&,因此,根据上面的引用折叠规则,参数类型实际上变为 A&。
- 当在 A 类型的右值上调用 foo 时,T 解析为 A,因此参数类型变为 A&&。
现在,当我将鼠标悬停在对auto_cast( 5.0f ) 的调用上时,工具提示正确地将其返回值显示为auto_cast_wrapper<float>。这意味着编译器正确地遵循了规则 2:
当在 A 类型的右值上调用 foo 时,T 会解析为 A。
既然我们有一个auto_cast_wrapper<float>,构造函数应该实例化一个float&&。但是错误消息似乎暗示它实例化了一个float的值。
这是完整的错误消息,再次显示 T=float 正确但 T&& 参数变为 T?
main.cpp(17): error C2440: 'initializing' : cannot convert from 'float' to 'float &&' You cannot bind an lvalue to an rvalue reference main.cpp(17) : while compiling class template member function 'auto_cast_wrapper<T>::auto_cast_wrapper(T &&)' with [ T=float ] main.cpp(33) : see reference to class template instantiation 'auto_cast_wrapper<T>' being compiled with [ T=float ]
有什么想法吗?
【问题讨论】:
-
你有没有机会把问题集中一点?与其将编辑内容作为单独的段落放在底部,不如将它们编辑到问题本身。作为读者,我不需要知道您将内容附加到问题的顺序,我只想阅读问题的最佳版本。如果您想自己发布答案,请将其作为实际答案,而不是作为问题底部的另一段。事实上,如果我什至想知道这个问题是关于什么的,我就必须阅读大量的文本和代码。
-
@jalf:是的,对不起,jalf。我不想创建单独的答案,因为 DeadMG 已经正确回答了。我想我只是认为我这样做是不礼貌的,尽管我认为对它的一些澄清不会让其他人在未来读到这篇文章。额外的问题可能应该是一个完全独立的问题,因为它与原始问题没有真正的关系。
-
在 SO 上,对已经回答的问题发布新的、更好的答案并没有错。如果您对此感觉不好,请接受 DeadMG 的回答,但在其下方发布您自己的回答。 :)
-
@jalf:好的,我创建了一个单独的答案并将其恢复为原始问题。还是有点长,但说明了我的谬误思路。
标签: c++ c++11 rvalue-reference