В моей структуре компилятора (который будет выпущен Sometime Soon ™) вы передаете элементы информации, такие как токены, в объект компилятора, а затем вызовите finalize
, чтобы указать конец потока.
Было бы плохо уничтожить объект, не вызвав finalize
, потому что он не вытолкнул бы весь его выход. Тем не менее finalize
не может быть выполнен деструктором, поскольку он может генерировать исключение, а также неправильно спрашивать finalize
для получения большего объема вывода, если парсер уже прерывается.
В случае, когда весь вход уже инкапсулирован другим объектом, приятно передать вход в объект компилятора rvalue.
pile< lexer, parser >(output_handler).pass(open_file("source.q"));
Без специальной поддержки, то это должно быть неправильным, потому что finalize
не вызывался. Интерфейс не должен позволять пользователю делать такую вещь вообще.
Первое, что нужно сделать, это исключить случай, когда finalize
никогда не вызывается. Приведенный выше пример запрещен, если прототип регулируются с именующим рефом-классификатором, как это:
void pass(input_file f) & {
process_the_file();
}
Это делает комнату, чтобы добавить еще одну перегрузки, которая должным образом объект обеспечивающих окончательную. Это rvalue ref-qual, поэтому он выбирается, только если вызывается на объект, который истекает.
void pass(input_file f) && {
pass(std::move(f)); // dispatch to lvalue case
finalize();
}
Теперь пользователю практически никогда не нужно беспокоиться о запоминании называть finalize
, так как большинство объектов компилятора, в конечном счете экземпляра в качестве временных.
Обратите внимание, что это не относится к квалифицированным членам. Любая функция может иметь отдельные перегрузки для t &
и t &&
. Путь pass
фактически в настоящее время реализуются использует совершенную переадресацию, а затем откатывается, чтобы определить правильную семантику:
template< typename compiler, typename arg >
void pass(compiler && c, arg a) {
c.take_input(a);
if (! std::is_reference<compiler>::value) {
c.finalize();
}
}
Есть много способов приблизиться к перегрузке. На самом деле, неквалифицированные функции-члены необычны в , но не заботятся о категории (lvalue или rvalue) объекта, на который они вызваны, и не передают эту информацию в функцию. Любой параметр функции, кроме неявного this
, должен сказать что-то о категории его аргумента.
С компиляторами, поддерживающими его сейчас, я ожидаю, что вскоре появится статья или две темы. – chris
gcc только что реализовал его в 4.8.1, поэтому не многие люди стали использовать эту функцию еще. –
В принципе, если вы хотите, чтобы пользователи не создавали постоянные объекты класса, а использовали только временные, вы можете добиться этого, выполнив нужные функции-члены '&&'. –