Почему буквальный оператор не может быть шаблонизирован нормально? - PullRequest
1 голос
/ 13 февраля 2020

В настоящее время я работаю над деревом выражений времени компиляции и хотел использовать оператор литерала для создания выражения из литерала. Поскольку все литералы разрешены в качестве выражения, я хотел создать шаблон литерального оператора, например:

template <typename T>
constexpr auto operator""_ve(T value)
{
    return value_expression(value);
}

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

* 1005. *

Почему это? Нужно ли указывать каждую перегрузку вручную?

1 Ответ

1 голос
/ 13 февраля 2020

Действительно ли мне нужно указывать каждую перегрузку вручную?

Да.

Литеральные операторы не вызываются с помощью разрешения перегрузки (не совсем). Разрешение перегрузки может делать такие вещи, как неявное преобразование или другие неприятные вещи. Поскольку литеральные операторы (как правило) вызываются компилятором для значений, сгенерированных во время компиляции, рекомендуется убедиться, что писатель литерального оператора получает литеральное значение whole (так же, как компилятор может предоставить, конечно) не преобразованное значение.

Это на самом деле довольно важно. Рассмотрим случай, когда вы хотите написать литерал, который принимает целочисленные значения, но , а не значения с плавающей точкой. То есть 12.3_lit должно быть ошибкой компиляции. Ваша подпись для вашего оператора займет unsigned long long, но long double неявно преобразуется в unsigned long long. Следовательно, 12.3_lit будет действительным, если вы не хотите, чтобы оно было.

Теперь теоретически вы можете избежать такого сценария ios, = delete явно используя сигнатуры с плавающей точкой. Но ... UDL были изобретены в то время, когда = delete на самом деле не было чем-то особенным, так что это не обязательно было вариантом.

Чтобы избежать этого сценария ios, логический оператор диспетчерской логики c явно ищет определенный набор сигнатур (в зависимости от типа обрабатываемого литерала). Если у вас нет перегрузки long double для оператора (или необработанной буквенной версии), то при обнаружении 12.3_lit система не найдет подходящей функции и выдаст ошибку компиляции.

Поскольку система ищет указанные c сигнатуры, а не использует разрешение перегрузки, сигнатуры литеральных операторов (включая шаблоны) ограничены точным и только сигнатурами, которые будет искать логический оператор диспетчерской логики c для . Не больше, не меньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...