簡體   English   中英

防止 function 接受 const std::string& 接受 0

[英]Prevent function taking const std::string& from accepting 0

值得一千字:

#include<string>
#include<iostream>

class SayWhat {
    public:
    SayWhat& operator[](const std::string& s) {
        std::cout << s << "\n";
        return *this;
    }
};

int main() {
    SayWhat ohNo;
    // ohNo[1]; // Does not compile. Logic prevails.
    ohNo[0]; // you didn't! this compiles.
    return 0;
}

將數字 0 傳遞給接受字符串的括號運算符時,編譯器不會抱怨。 相反,這會在進入方法之前編譯並失敗:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid

以供參考:

> g++ -std=c++17 -O3 -Wall -Werror -pedantic test.cpp -o test && ./test
> g++ --version
gcc version 7.3.1 20180303 (Red Hat 7.3.1-5) (GCC)

我猜

編譯器隱式使用std::string(0)構造函數進入該方法,這會產生同樣的問題(谷歌上述錯誤),沒有充分的理由。

問題

有沒有辦法在 class 端解決這個問題,所以 API 用戶感覺不到這個並且在編譯時檢測到錯誤?

也就是說,添加一個重載

void operator[](size_t t) {
    throw std::runtime_error("don't");
}

不是一個好的解決方案。

std::string(0)有效的原因是0是 null 指針常量。 所以 0 匹配帶有指針的字符串構造函數。 然后代碼運行與不能將 null 指針傳遞給std::string的前提條件相沖突。

只有文字0會被解釋為 null 指針常量,如果它是int中的運行時值,則不會遇到此問題(因為重載解析將改為尋找int轉換)。 文字1也不是問題,因為1不是 null 指針常量。

由於這是一個編譯時問題(文字無效值),您可以在編譯時捕獲它。 添加此表單的重載:

void operator[](std::nullptr_t) = delete;

std::nullptr_tnullptr的類型。 它將匹配任何null 指針常量,無論是00ULL還是nullptr 並且由於function被刪除,在重載解析時會造成編譯時錯誤。

一種選擇是聲明operator[]()private重載,它接受一個整數參數,並且不定義它。

此選項適用於所有 C++ 標准(1998 年起),不像void operator[](std::nullptr_t) = delete等選項在 C++11 中有效。

operator[]()設為private成員將導致示例ohNo[0]出現可診斷錯誤,除非該表達式由成員 function 或 class 的friend使用。

If that expression is used from a member function or friend of the class, the code will compile but - since the function is not defined - generally the build will fail (eg a linker error due to an undefined function).

使用 string_view 有幫助(有點)

從 C++17 開始,我們有std::string_view class 它完全適用於這種用例,將非擁有的對類字符串對象的引用傳遞給只讀取字符串的函數。 您應該認真考慮將其用於此類運算符。

現在, std:: string_view有它自己的設置問題(請參閱:足夠的string_view to hang 我們自己),但在這里它會給你一個有用的警告。 如果您更換:

    SayWhat& operator[](const std::string& s) {

    SayWhat& operator[](std::string_view s) {

你用--std=c++17 -Wall編譯,你得到:

<source>: In function 'int main()':
<source>:16:11: warning: null argument where non-null required (argument 2) [-Wnonnull]
   16 |     ohNo[0]; // you didn't! this compiles.
      |           ^

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM