1

C++ プロジェクトを MSVC 2008 から 2010 にアップグレードしていますが、新しい CComBSTR 移動コ​​ンストラクター [CComBSTR( CComBSTR&& )] が原因で、あいまいな呼び出しが原因でコンパイラ エラーが発生します。

基本的に、CComBSTR へのキャスト演算子を持つ std::wstring に非常によく似た String クラスがあります。これは、次のコードに似ています。

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 右辺値に変換され、CComBSTR のコピー コンストラクター (const CComBSTR& を取る) が呼び出されて objectName を構築するため、これは機能します。

ただし、C++0x を使用する VS2010 では、CComBSTR 右辺値がコピー コンストラクターと移動コンストラクターの両方に適合するように見えるため、コンパイラはあいまいな呼び出しエラーを返します。

少し不器用ですが、この問題に対する私の解決策は、GetName への呼び出しを static_cast することです。

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

どちらの行もエラーなしでコンパイルされますが、これが違法か、悪い習慣か、未定義かについてアドバイスが必要です。ありがとうございました。

4

1 に答える 1

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&&) への呼び出しを呼び出すか無視します。この疑わしいバグを回避するための私の推奨事項は、次のとおりです。

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

これはあなたと同等です:

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

しかし、それほど怖くはありません (そして効率的です)。static_cast を使用したい場合は、CComBSTR&& へのキャストを使用します。これは、おそらく const 左辺値からの構築よりも効率的です。

于 2011-03-08T01:15:52.490 に答える