For example, if I use UInt8 constant for if condition then only one branch is evaluated:
```sql
SELECT if(1, 'success', throwIf(1, 'Executing FALSE branch'))

┌─'success'─┐
│ success   │
└───────────┘

1 rows in set. Elapsed: 0.003 sec.
```

But if I use some constant expression, then both branches are evaluated:
```sql
SELECT if(empty(''), 'success', throwIf(1, 'Executing FALSE branch'))

0 rows in set. Elapsed: 0.003 sec.

Received exception from server (version 21.12.2):
Code: 395. DB::Exception: Received from localhost:9000. DB::Exception: Executing FALSE branch: While processing if(empty(''), 'success', throwIf(1, 'Executing FALSE branch')). (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO)
```
{
    const auto col = checkAndGetColumn<ColumnVector<T>>(column);
    if (!col)
        return false;
    std::transform(
            col->getData().cbegin(), col->getData().cend(), res.begin(),
            [](const auto x) { return !!x; });
    return true;
}
void convertAnyColumnToBool(const IColumn * column, UInt8Container & res)
{
    if (!tryConvertColumnToBool<Int8>(column, res) &&
        !tryConvertColumnToBool<Int16>(column, res) &&
        !tryConvertColumnToBool<Int32>(column, res) &&
        !tryConvertColumnToBool<Int64>(column, res) &&
        !tryConvertColumnToBool<UInt16>(column, res) &&
        !tryConvertColumnToBool<UInt32>(column, res) &&
        !tryConvertColumnToBool<UInt64>(column, res) &&
        !tryConvertColumnToBool<Float32>(column, res) &&
        !tryConvertColumnToBool<Float64>(column, res))
        throw Exception("Unexpected type of column: " + column->getName(), ErrorCodes::ILLEGAL_COLUMN);
}
template <class Op, typename Func>
static bool extractConstColumns(ColumnRawPtrs & in, UInt8 & res, Func && func)