Candidate function not viable: no known conversion from 'System::WideChar *' (aka 'wchar t *') to 'const char *' エラーの対処方法

提供: Support
移動先: 案内検索

対象となる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つの方法があります。

  1. 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. ワイド文字(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関数へ変更してください。


関連情報

Clang 拡張 C++ コンパイラと旧世代の C++ コンパイラの違い