Repository: realm/realm-swift
File: Realm/RLMQueryUtil.mm (Objective-C++)

Code before:

    auto as_subexpr = util::overload{
        [](StringData value) { return make_subexpr<ConstantStringValue>(value); },
        [](BinaryData value) { return make_subexpr<ConstantStringValue>(StringData(value.data(), value.size())); },
        [](Mixed value) {
            // When Mixed is null calling `get_type` will throw an exception.
            if (value.is_null())
                return make_subexpr<ConstantStringValue>(value.get_string());
            switch (value.get_type()) {
                case DataType::Type::String:
                    return make_subexpr<ConstantStringValue>(value.get_string());
                case DataType::Type::Binary:
                    return make_subexpr<ConstantStringValue>(StringData(value.get_binary().data(), value.get_binary().size()));
                default:
                    REALM_UNREACHABLE();
            }
        },
        [](auto& c) { return c.clone(); }
    };
    auto left = as_subexpr(column);
    auto right = as_subexpr(value);

    bool caseSensitive = !(predicateOptions & NSCaseInsensitivePredicateOption);
    constexpr auto flags = kCFCompareDiacriticInsensitive | kCFCompareAnchored;
    switch (operatorType) {
        case NSBeginsWithPredicateOperatorType:
        case NSEndsWithPredicateOperatorType:
        case NSContainsPredicateOperatorType:
            add_substring_constraint(value, make_diacritic_insensitive_constraint(operatorType, caseSensitive, std::move(left), std::move(right)));
            break;
        case NSNotEqualToPredicateOperatorType:
            m_query.and_query(make_diacritic_insensitive_constraint<NotEqual<flags>>(caseSensitive, std::move(left), std::move(right)));
            break;
        case NSEqualToPredicateOperatorType:
            m_query.and_query(make_diacritic_insensitive_constraint<Equal<flags>>(caseSensitive, std::move(left), std::move(right)));
            break;
        case NSLikePredicateOperatorType:
            throwException(@"Invalid operator type",
                           @"Operator 'LIKE' not supported with diacritic-insensitive modifier.");
        default:
            unsupportedOperator(RLMPropertyTypeString, operatorType);
    }
}

id value_from_constant_expression_or_value(id value) {
    if (NSExpression *exp = RLMDynamicCast<NSExpression>(value)) {
        RLMPrecondition(exp.expressionType == NSConstantValueExpressionType,
                        @"Invalid value",
                        @"Expressions within predicate aggregates must be constant values");
        return exp.constantValue;
    }

Review comment (suggestion):
```suggestion
        // Core only implements these for Columns<Mixed> due to Dictionary being Mixed internal
```

Code after:
                condition.Or();
            }

            condition.and_query(make_diacritic_sensitive_constraint(operatorType, caseSensitive, column, m));
        }
    }
    switch (operatorType) {
        case NSBeginsWithPredicateOperatorType:
        case NSEndsWithPredicateOperatorType:
        case NSContainsPredicateOperatorType:
            add_substring_constraint(value, std::move(condition));
            break;

        default:
            m_query.and_query(std::move(condition));
            break;
    }
}

template <typename C, typename T>
void QueryBuilder::add_diacritic_sensitive_string_constraint(NSPredicateOperatorType operatorType,
                                                             NSComparisonPredicateOptions predicateOptions,
                                                             C&& column, T&& value) {

    if constexpr (is_any_v<C, Columns<Dictionary>> && is_any_v<T, Columns<StringData>, Columns<BinaryData>>) {
        // Core only implements these for Columns<Mixed> due to Dictionary being Mixed internall
        throwException(@"Unsupported predicate",
                       @"String comparisons on a Dictionary and another property are only implemented for AnyRealmValue properties.");
    }
    else {
        do_add_diacritic_sensitive_string_constraint(operatorType, predicateOptions, std::forward<C>(column), std::forward<T>(value));
    }
}

template <typename C, typename T>
void QueryBuilder::add_string_constraint(NSPredicateOperatorType operatorType,
                                         NSComparisonPredicateOptions predicateOptions,
                                         C&& column, T&& value) {
    if (!(predicateOptions & NSDiacriticInsensitivePredicateOption)) {
        add_diacritic_sensitive_string_constraint(operatorType, predicateOptions, std::forward<C>(column), std::forward<T>(value));
        return;
    }

    auto as_subexpr = util::overload{
        [](StringData value) { return make_subexpr<ConstantStringValue>(value); },
        [](BinaryData value) { return make_subexpr<ConstantStringValue>(StringData(value.data(), value.size())); },
        [](Mixed value) {
            // When Mixed is null calling `get_type` will throw an exception.
            if (value.is_null())
                return make_subexpr<ConstantStringValue>(value.get_string());
            switch (value.get_type()) {