Есть ли такая идиома, как `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

Есть предложения?

12 голосов | спросил Tilman Vogel 11 J0000006Europe/Moscow 2015, 22:38:07

6 ответов


0

Единственный способ использовать эту идиому, сохраняя понятность вашего кода, - это если ваша функция возвращает объект, который можно преобразовать в bool таким образом, что true означает, что вы хотите взять ветку, а false означает, что вы не заботитесь об этом. Все остальное просто приведет к коду только для записи.

Одним из таких объектов, который может быть релевантным, является boost::optional . Дано:

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

Вы можете использовать идиому, которую вы хотите, естественным образом:

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

Это также имеет дополнительное преимущество, поскольку я считаю сообщение об ошибке optional более семантически значимым, чем проверка на наличие пустой ошибки. сообщение.

ответил Barry 11 J0000006Europe/Moscow 2015, 22:59:32
0

Нет. Здесь нет такой идиомы, и нет синтаксиса , как это!

Кроме того, вы достигли точки, в которой больше не стоит делать ваш код все более и более запутанным.

Просто напишите, как сейчас.

Если вы действительно не хотите утечку области, введите новую область:

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

Я довольно часто использую этот шаблон, хотя меня справедливо обвиняют в пристрастии к сфере видимости, поэтому примите это как хотите.

ответил Lightness Races in Orbit 11 J0000006Europe/Moscow 2015, 22:56:48
0

В принципе нет чистого способа сделать это.

Я бы порекомендовал вам просто определить дополнительный блок вокруг 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

Но я не особенно люблю это решение.

ответил tux3 11 J0000006Europe/Moscow 2015, 22:59:50
0

Вы можете использовать:

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

но это уродливо и делает ваш код трудным для чтения. Поэтому, пожалуйста, не надо.

ответил immibis 12 J0000006Europe/Moscow 2015, 04:49:26
0
if(auto message = maybe_filter( getError(arg), [](auto&&str){
  return !str.isEmpty();
}) {
}

где maybe_filter принимает T и тестовая функция и возвращает optional<T>. optional<T> пусто, если проверяется тестовая функция в T дает вам ложное значение, а T в противном случае.

Или действительно измените ваш API получения ошибок, чтобы он возвращал необязательную строку.

ответил Yakk - Adam Nevraumont 12 J0000006Europe/Moscow 2015, 04:37:14
0

Вы можете использовать лямбду.

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

error_string_handler(someFunctionReturningAnErrorString(arg));
ответил jxh 12 J0000006Europe/Moscow 2015, 03:57:14

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132