11

最近、メソッドのオーバーロードが導入されたため、アプリケーションが失敗し始めました。最後にそれを追跡すると、新しいメソッドが予想外の場所で呼び出されています。

我々は持っていた

setValue( const std::wstring& name, const std::wstring& value );

std::wstring avalue( func() );
setValue( L"string", avalue );
std::wstring bvalue( func2() ? L"true", L"false" );
setValue( L"bool", bvalue );
setValue( L"empty", L"" );

bool 値が格納されるときに同じ文字列を使用するように変更されました (文字列の内部データ ストレージ)。

setValue( const std::wstring& name, const std::wstring& value );
setValue( const std::wstring& name, const bool& value );

std::wstring avalue( func() );
setValue( L"string", avalue );
setValue( L"bool", func2() );
setValue( L"empty", L"" ); << --- this FAILS!?!

L"" の問題は、それが暗黙的にキャストされることであり、以前は std::wstring であることを喜んでいましたが、bool であることは好まれませんでした。MSVC コンパイラは文句を言ったり、警告を発したりしないので、setValue( L"empty", L"" ); することが

setValue( L"empty", std::wstring() );

他の誰かが後で来て、単に setValue( L"empty", L"" ); を使用する可能性があります。この問題をもう一度追跡する必要があります。

メソッドで明示的に使用することを考えましたが、この使用法では有効なキーワードではありません。コンパイラにこれについて不平を言う、または問題を防ぐ方法はありますか? それ以外の場合は、bool を取るメソッドの名前を変更して、間違った推測ができないようにすることを考えています。

4

5 に答える 5

12

まず、この問題の原因: C++ 標準1では、変換シーケンスの順序が定義されています。ユーザー定義の変換シーケンスは、標準の変換シーケンスよりも悪いと言われています。あなたの場合に起こることは、文字列リテラルがブール変換を受けることです(で定義されています。これは標準の変換です)。他のオーバーロードを使用した場合に必要になるユーザー定義の変換は使用しません。[over.ics.rank]/2.14.12std::wstring

いずれかのオーバーロードの名前を単純に変更するか、文字列リテラルを直接受け入れるオーバーロードを追加することをお勧めします (パラメーター type を使用wchar_t const*)。


1)

暗黙的な変換シーケンスの基本形式を比較する場合 ( で定義[over.best.ics])

(2.1) 標準の変換シーケンスは、ユーザー定義の変換シーケンスまたは省略記号の変換シーケンスよりも優れた変換シーケンスであり、
(2.2) ユーザー定義の変換シーケンスは、省略記号の変換シーケンスよりも優れた変換シーケンスです。

于 2008-11-25T02:38:26.520 に答える
8

L"" はワイド文字列へのポインタです。コンパイラは、bool への変換が std::wstring への変換よりも優先されると認識しています。

この問題を解決するには、新しい setValue を導入します。

void setValue(std::wstring const& name, const wchar_t * value);
于 2008-11-25T03:03:34.440 に答える
2

bool は組み込み型であるため、wchar_t から bool への変換が推奨されます。最も簡単な解決策は、 wchar_t 配列を取り、そこに明示的にキャストするオーバーロードを追加することです。

setValue( const std::wstring& name, const wchar_t s[] )
{
     setValue(name, wstring(s));
}
于 2008-11-25T03:19:28.387 に答える
1

少し単純化するために、次のコード

#include <iostream>
using namespace std;

void f(const string &s)
{  cout << "string version called" << endl;  }

void f(const bool &b)
{  cout << "bool version called" << endl;  }

int main()
{  f("Hello World");  }

「と呼ばれるブールバージョン」を出力します。コードが空の文字列でのみ失敗することは確かですか?

于 2008-11-25T02:48:27.357 に答える
0

新しい関数を bool 以外の型にすることもできます (bool の単なるプロキシかもしれません)。これはリテラル文字列から変換できません。しかし、実際には、ブール取得関数の名前を変更するだけで済みます。

于 2008-11-25T02:37:52.607 に答える