我正在将C ++项目从MSVC 2008升级到2010,并且由于新的CComBSTR移动构造函数[CComBSTR(CComBSTR&&)],因为调用模糊,我收到编译器错误。
基本上,我们有一个String类,与std :: wstring非常相似,它具有CComBSTR的强制转换运算符。这与以下代码类似:
class CString {
public:
// ...
operator CComBSTR() {
CComBSTR temp;
/* Encoding conversion here */
return temp;
}
}
class CObjectConfig {
public:
CString GetName() const { return m_name; }
private:
CString m_name;
}
现在,在代码的某些地方,我们会执行以下操作:
CObjectConfig config = GetObjectConfig();
CComBSTR objectName( config.GetName() );
在VS2008中,这将起作用,因为CString对象将被隐式转换为CComBSTR rvalue,并且将调用CComBSTR的复制构造函数(采用const CComBSTR&)来构造objectName。
在带有C ++ 0x的VS2010中,编译器给出了一个模糊的调用错误,因为CComBSTR rvalue似乎适合复制构造函数和移动构造函数。
虽然有点笨拙,但我解决这个问题的方法是static_cast调用GetName:
CComBSTR objectName( static_cast<const CComBSTR&>( config.GetName() ) );
// or
CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );
两行都编译没有错误,但我需要你的建议,这是非法的,坏的做法还是未定义的。谢谢。
答案 0 :(得分:1)
这对我来说就像是一个VC2010错误。要不然,或者我错误地模仿了我的计算机上的情况(我没有VC2010)。这就是我正在做的事情:
#include <iostream>
class CComBSTR
{
public:
CComBSTR() {std::cout << "CComBSTR()\n";}
CComBSTR(const CComBSTR&) {std::cout << "CComBSTR(const CComBSTR&)\n";}
CComBSTR(CComBSTR&&) {std::cout << "CComBSTR(CComBSTR&&)\n";}
};
class CString {
public:
// ...
operator CComBSTR() {
CComBSTR temp;
/* Encoding conversion here */
return temp;
}
};
class CObjectConfig {
public:
CString GetName() const { return m_name; }
private:
CString m_name;
};
CObjectConfig GetObjectConfig()
{
return CObjectConfig();
}
int main()
{
CObjectConfig config = GetObjectConfig();
CComBSTR objectName( config.GetName() );
}
对于g ++ - 4.4和clang(使用-std = c ++ 0x),这个编译很好。它可以呼叫或省略对CComBSTR(CComBSTR&amp;&amp;)的呼叫。我建议解决这个疑似错误的原因很简单:
CComBSTR objectName( CComBSTR(config.GetName()) );
这相当于你的:
CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );
但不是那么可怕(并且同样有效)。如果你想继续使用static_cast,那么请使用强制转换为CComBSTR&amp;&amp;因为这可能比const lvalue的构造更有效。