Candidate function not viable: no known conversion from 'System::WideChar *' (aka 'wchar t *') to 'const char *' エラーの対処方法
対象となるIDEのバージョン
- C++Builder 10.3以降
対象となるコンパイラ
- bcc32c、bcc64(Clangコンパイラ)
問題
C++Builder 2007などの古いバージョンで作成したプロジェクトをC++Builderの新バージョンへ移行し、コンパイルするとエラーが発生することがあります。
void __fastcall TForm1::Button1Click(TObject *Sender) {
char *text = new char[Edit1->Text.Length() + 1];
strcpy(text, Edit1->Text.c_str());
ShowMessage(text);
}
上記のサンプルコードは、フォーム上にボタン(Button1)とエディットボックス(Edit1)が配置されており、Button1のクリックイベントが発生すると、new演算子によってEdit1に入力されている文字数分の動的配列(text)がローカルに確保されます。そしてEdit1に入力されている文字列がtextポインタへコピーされ、最後にメッセージボックスによってtextポインタの内容が表示されるというプログラムのコード例です。
例えば、上記のプログラムコードをコンパイルすると、以下のコンパイルエラーが発生します。
bcc32cの場合:
[bcc32c エラー] no matching function for call to 'strcpy'
_str.h(120): candidate function not viable: no known conversion from 'System::WideChar *' (aka 'wchar_t *') to 'const char *' for 2nd argument
bcc64の場合:
[bcc32c エラー] no matching function for call to 'strcpy'
_str.h(120): candidate function not viable: no known conversion from 'System::WideChar *' (aka 'wchar_t *') to 'const char *' for 2nd argument
但し、このプログラムはC++Builder2007までは同じコードでコンパイルエラーは発生しませんでした。
C++Builder 10.3以降では、32ビットC++コンパイラのデフォルトは、bcc32ではなくbcc32cに変更されているため、コンパイラとしてbcc32を選択している場合は、エラーメッセージが異なります。対処方法はこちらを参照ください。
原因
上記のエラーメッセージは、strcpy関数のコピー元とコピー先の引数の型が不一致であることが原因です。
C++Builder2009からデフォルトで扱う文字列型は、AnsiString型からUnicodeString型へ置き換わっており、例えば、EditコンポーネントのTextプロパティや、ButtonコンポーネントのCaptionプロパティなど内部的に扱う文字列型は全てUnicodeString型に置き換わっています。文字列型のポインタを返すc_strメソッドの仕様もC++Builder2009以降では変更されています。
(c_strメソッドが返すポインタ型は、char*からwchar_t*に変更)
非Unicode対応であるC++Builder2007迄のバージョンではコンパイルエラーは発生しませんでしたが、C++Builder2009以降ではプログラムコードを修正する必要があります。
解決
コンパイルエラーに対処するには、以下の2つの方法があります。
- AnsiString型へ明示的にキャストする方法
void __fastcall TForm1::Button1Click(TObject *Sender) { char *text = new char[Edit1->Text.Length() + 1]; strcpy(text, AnsiString(Edit1->Text).c_str()); ShowMessage(text); }
- AnsiString型へ明示的にキャストすることで、C/C++言語の従来の1バイト文字型(char型)との互換を保つことができます。
- 但し、この方法ではUnicode文字は表示することはできません。
- ワイド文字(2バイト)対応の文字型や関数を利用する方法
void __fastcall TForm1::Button1Click(TObject *Sender) { wchar_t *text=new wchar_t[Edit1->Text.Length()+1]; wcscpy(text,Edit1->Text.c_str()); ShowMessage(text); }
- UnicodeString型は、1文字あたりのサイズが2バイトになります。そのためC/C++言語で扱うchar型では互換が無く、Unicode対応のwchar_t型を利用する必要があります。また文字列を扱う関数も従来の1バイト文字対応(str~)のものではなく、Unicodeに対応した文字列関数(wcs~)を利用する必要があります。
- 例えば、文字列をコピーする関数は、strcpyからwcscpy関数へ変更してください。