2015-06-11 10 views
12

我經常使用公共當你在檢索值的表達式上進行分支時,是否有像if(Value * value = getValue())這樣的成語?

if (Value * value = getValue()) 
{ 
    // do something with value 
} 
else 
{ 
    // handle lack of value 
} 

現在,我還經常做

QString error = someFunctionReturningAnErrorString(arg); 
if (!error.isEmpty()) 
{ 
    // handle the error 
} 
// empty error means: no error 

這就是罰款,但我想error變量的作用域到if - 塊。有沒有一個很好的成語呢?顯然,我可以將整個部分包裹在另一個塊中。

顯然,這不工作:

if(QString error = someFunctionReturningAnErrorString(arg), !error.isEmpty()) 
{ 
    // handle the error 
} 
// empty error means: no error 

而且不幸的是(但有充分理由)的QString不能轉換爲bool,所以這不起作用或者:

if(QString error = someFunctionReturningAnErrorString(arg)) 
{ 
    // handle the error 
} 
// empty error means: no error 

任何建議?

+1

我已經改變了我的編碼準則,以便賦值語句永遠不會出現在條件表達式中。這是爲了避免在if語句中輸入「==」與「=」的問題。我讓編譯器負責臨時變量。 –

+0

您是否需要在錯誤處理中使用錯誤變量?你可以用'if(!someFunctionReturningAnErrorString(arg).isEmpty())'代替。 –

+3

不要不必要地縮短你的代碼,只需要一些中間變量,使得閱讀和調試代碼更容易。 (換句話說:您的編碼風格混淆) –

回答

6

使用習語,同時仍保持你的代碼可以理解的是,如果你的函數返回一個對象,它是換股的方式爲bool是true表示要採取分支和false意味着你不在乎的唯一途徑關於它。其他任何事情只會導致只寫代碼。

可能相關的一個這樣的對象恰好是boost::optional。鑑於:

boost::optional<QString> someFunctionReturningAnErrorString(T arg); 

你可以使用你想要的成語以自然的方式:

if (auto error = someFunctionReturningAnErrorString(arg)) { 
    // ... 
} 

這也有額外的好處,我會考慮的optional錯誤消息,不必檢查更多的語義上有意義爲空的錯誤消息。

+3

「我會考慮一個'可選的'錯誤消息更多的語義意義比不必檢查一個空的錯誤消息。「+1 – emlai

+1

我接受了這個答案,因爲我認爲這是對我的用例進行重新設計的最好建議,即使它沒有提供一個通用的解決方案來處理Yakk和jxh的答案對任意表達式的幫助。 –

11

沒有這樣的成語,並且沒有語法這樣!

此外,您已經達到使代碼越來越模糊不再值得的地步。

只需現在寫就可以了。

如果你真的不想範圍泄漏,引入一個新的範圍:

{ 
    const QString error = someFunctionReturningAnErrorString(arg); 
    if (!error.isEmpty()) { 
     // handle the error 
    } 
} 
// The above-declared `error` doesn't exist down here 

我用這種模式相當多,雖然我已經相當指責範圍上癮的,所以想拿就拿吧。

+0

FFS評論被刪除沒有很好的理由 –

3

基本上沒有乾淨的方法來做到這一點。

我建議你剛纔定義if圍繞一個額外的塊,但如果你真的想有一個確切的語法,一個解決辦法是宣佈自己的類包裝QString

struct ErrorString 
{ 
    ErrorString(QString&& s) : s{move(s)} {} 
    operator bool() {return !s.isEmpty();} 

    QString s; 
}; 

然後你可以寫:

if(ErrorString error = someFunctionReturningAnErrorString(arg)) 
{ 
    // handle the error 
} 
// empty error means: no error 

但我不是特別喜歡這個解決方案。

+0

You也可以爲'QString'添加一個轉換運算符 – jxh

+0

@jxh對,但後果太深 –

+0

@ tux3謝謝,但我喜歡'可選的'>'方案更好一點,它非常相似 –

0

您可以使用lambda。

auto error_string_handler = [](QString && error) { 
    if (error.isEmpty()) return; 
    //... 
} 

error_string_handler(someFunctionReturningAnErrorString(arg)); 
+0

好的,但我需要爲每種類型的錯誤處理單獨使用lambda表達式,並且錯誤處理在視覺上與產生錯誤的錯誤分開(並且以相反的順序)。但是,感謝這個建議! –

1
if(auto message = maybe_filter(getError(arg), [](auto&&str){ 
    return !str.isEmpty(); 
}) { 
} 

其中maybe_filter需要T和測試功能,並返回optional<T>。如果評估T上的測試功能會導致錯誤,則optional<T>爲空,否則爲T

或者真的,修改您的錯誤獲取API返回一個可選的字符串。

+0

好吧,如果我通常只檢查'isEmpty()',我也可以使用一個'ignore_empty()'函數,它的測試函數是硬編碼的,這對我們來說非常方便即 –

2

你可以使用:

for(QString error = someFunctionReturningAnErrorString(arg); !error.isEmpty(); /* too bad 'break' is invalid here */) 
{ 
    // handle the error 
    break; 
} 

但這是醜,使你的代碼難以閱讀。所以請不要。

+0

這正是我所尋找的;-)只有退縮(除了醜)是我不能輕易添加一個'else'子句... –

相關問題