web-dev-qa-db-ja.com

グローバルconst char []をconstexpr string_viewに置き換える落とし穴はありますか?

私たちのチームは10年以上前のC++コードベースで作業しており、最近C++ 17コンパイラに切り替えました。そこで、コードを最新化する方法を探しています。 YouTubeでのカンファレンストークで、const char*グローバル文字列をconstexpr string_viewに置き換えるという提案を聞きました。

このようなconst char*グローバル文字列定数がコードに多数含まれているので、知っておく必要のある問題や潜在的な問題があるかどうかを確認したいと思いますか?

17
PixelSupreme

これらの問題は、認識しておく価値があります。

  1. std::string_viewは、nullで終了する必要はありません。したがって、一部のconst char*string_viewで置き換え、以前にnullで終了したchar*サブストリングの構築をstring_viewを介してstd::string_view::substrで置き換える場合、nullで終了する文字列を必要とするAPIに基本となるポインタを渡すことはできません。例(UBなしですが、これも簡単に構築できます):

    void legacy(const char *str) {
       std::printf("%s\n", str);
    }
    
    constexpr std::string_view sv1 = "abcde";
    constexpr std::string_view sv2 = sv1.substr(0, 2); // view on "ab"
    
    legacy(sv2.data()); // Not intended: prints "abcde" 
    
  2. std::stringからconst char*を暗黙的に構築することはできますが、std::string_viewを使用してそれを行うことはできません。これは、ディープコピーが内部で行われるべきではなく、明示的に要求された場合にのみ行われるという考え方です。例:

    std::map<std::string, int> m;
    constexpr std::string_view sv = "somekey";
    constexpr const char *old = "somekey";
    
    m[old] = 42; // works as expected
    m[sv] = 42; // fails to compile
    m[std::string(sv)] = 42; // be explicit, this is ok
    

    プロジェクトでのグローバルconst char*インスタンスの既存の使用方法によっては、この動作をさまざまな場所で手動で行う必要がある場合があります。

14
lubgr