web-dev-qa-db-ja.com

std :: string_viewをconst char *に変換する方法は?

フラグ-std=c++17を使用してgcc-7.1でコンパイルすると、次のプログラムでエラーが発生します。

#include <string_view>
void foo(const char* cstr) {}
void bar(std::string_view str){
    foo(str);
}

エラーメッセージは

In function 'void bar(std::string_view)':
error: cannot convert 'std::string_view {aka std::basic_string_view<char>}' to 'const char*' for argument '1' to 'void foo(const char*)'
 foo(str);

他のライブラリ(abseil、bde)がconst char*に暗黙的に変換する同様のstring_viewクラスを提供するため、const char*への変換がないことに驚いています。

19
Justin Raymond

std::string_viewは、nullで終わる文字列を格納しないため、const char*への変換を提供しません。基本的に、最初の要素へのポインタと文字列の長さを格納します。これは、const char*を期待するfoo(他にどのようにサイズを取得するのですか?)のような、ヌル終了文字列を期待する関数に渡すことができないことを意味します。価値がある。

ビューにnullで終わる文字列があることが確実にわかっている場合は、 std::string_view::data を使用できます。

そうでない場合は、最初にstd::string_viewを使用することをお勧めします。保証されたヌル終了文字列std::stringが必要な場合は、これをお勧めします。ワンライナーの場合は、std::string(object).data()を使用できます。

26
Rakete1111

単にstd::string(string_view_object).c_str()を実行して、保証されたヌル終了一時コピーを取得します(そして、行末でクリーンアップします)。

これは、文字列ビューがnull終了を保証しないために必要です。たとえば、長いバッファの真ん中を見ることができます。

このユースケースが高価であり、ボトルネックであることが証明されている場合は、nullで終了するかどうかを追跡する拡張string_viewを書くことができます(基本的に、生のchar const*から構築された場合)。

次に、この拡張されたstring_viewを取得し、それをstd::stringにコピーするか、拡張されたstring_viewを直接保存し、適切にnullで終了したバッファーを返す暗黙的なcast-to -char const*を保持するヘルパータイプを記述できます。

次に、string_viewの代わりにコードベースのどこでもその拡張ヘルパータイプを使用して、文字列ビューとstd文字列の相互作用を強化して、std文字列バッファの最後に行くビューがある場合をキャッチします。

しかし、実際にはおそらくそれはやり過ぎです。

おそらく、const char*を使用するAPIをstring_viewに変更することをお勧めします。

foo(std::string(str).c_str())を呼び出すことができます。

5
Maxime Guinin