1

質問のタイトルが正しいことを願っています。

多くの null 以外で終了する char 配列といくつかの std::string 型を含む非常に大規模な/古いデータベースがあります。このデータベースを使用するツールを作成していますが、null 以外で終了する char 配列に関する安全性を確保したいと考えています。理想的には、開発者がツールを使いやすくするために、両方のタイプをサポートしたいと考えています。

void AddCell( const std::string & _cell_str );
void AddCell( const char * _cell_data, size_t _array_size );

ただし、問題が発生する可能性のある特定のシナリオがあります。新しい開発者が char 配列が null 以外で終了していることに気づかず、怠惰から std::string の暗黙的な変換を使用することにした場合、入力する必要がないためです。配列サイズの場合、std::string に不要な文字が表示される可能性があります。

どうすればこの問題に対処できますか? std::string の長さを指定するよう誰かに強制する必要がありますか? std::string オーバーロードされた関数を削除して、誰もが std::string から c_str() を使用するようにする必要がありますか? 理想的には、明示的なキーワードを使用するだけですが、コンストラクターでのみ使用できます。私は std::string の使用を避けるのをためらっています。

4

2 に答える 2

6

できることはさまざまです。それらの 1 つは、オーバーロードをdelete-ing することです。const char*

void AddCell(const std::string&);
void AddCell(const char*) = delete;
void AddCell(const char*,size_t);

関数を としてマークするとdelete、使用時にコンパイラ エラーが発生しますが、オーバーロードの候補関数のセットから削除されません。ユーザーがconst char*2 番目のオーバーロードを渡すと、オーバーロードが削除されたとコンパイラが叫びます。

もちろん、既知のサイズの配列にラッパーを提供して、リテラルを安全かつシームレスに渡すこともできます。

template <size_t N>
void AddCell(const char (&array)[N]) {
   AddCell(array, N);
}

リテラルは配列であり、最適な候補はテンプレートであり、適切なサイズAddCell("MyCell")のオーバーロードにディスパッチされるため、これにより が可能になります。(const char*,size_t)

于 2013-01-16T21:34:14.397 に答える
5

最初のオーバーロードを変更して、std :: string参照を取得する代わりに、std::stringからの暗黙的な変換を持つ作成した新しい型への参照を取得するようにすることができます。したがって、const char *からの暗黙の変換は表示されませんが、std::stringは問題なく実行されます。

于 2013-01-16T21:20:35.020 に答える