开发者

Move constructor (rvalue reference) in implicit conversion

I am upgrading a C++ project from MSVC 2008 to 2010, and because of the new CComBSTR move constructor [CComBSTR( CComBSTR&& )], I am getting a compiler error because of an ambiguous call.

Essentially, we have a String class, very si开发者_如何转开发milar to std::wstring that have a cast operator to CComBSTR. This is similator to the following code:

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;
}

Now, at some places in the code, we do the following:

CObjectConfig config = GetObjectConfig();
CComBSTR objectName( config.GetName() );

In VS2008, this would work because the CString object would be implicitly converted to a CComBSTR rvalue and the copy constructor of CComBSTR (taking a const CComBSTR&) would be called to construct objectName.

In VS2010 with C++0x however, the compiler gives an ambiguous call error because CComBSTR rvalue seems to fit both the copy constructor and the move constructor.

While a bit clumsy, my solution to this problem is to static_cast the call to GetName:

CComBSTR objectName( static_cast<const CComBSTR&>( config.GetName() ) );
// or
CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );

Both lines compile without error, but I need your advice on whether this is illegal, bad practice or undefined. Thank you.


This looks like a VC2010 bug to me. Either that, or I've incorrectly emulated your situation on my computer (I don't have VC2010). Here's what I'm doing:

#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() );
}

For me on g++-4.4 and clang (with -std=c++0x), this compiles fine. And it either calls or elides a call to CComBSTR(CComBSTR&&). My recommendation for working around this suspected bug is simply:

CComBSTR objectName( CComBSTR(config.GetName()) );

This is equivalent to your:

CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );

but not as scary looking (and just as efficient). If you want to stay with the static_cast, then go with cast to CComBSTR&& as this will probably be more efficient than construction from a const lvalue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜