Пропускать шаблоны args by const & or &&

У меня есть эта примерная программа:

#include <iostream>

template<typename Message, typename Decoration, typename PrintImpl>
void print_surrounded(Message&& msg, const Decoration& decoration, const PrintImpl& print_impl)
{
    print_impl(decoration); // should forward be used?
    print_impl(" ");
    print_impl(std::forward<Message>(msg));
    print_impl(" ");
    print_impl(decoration);
}

template<typename Message, typename PrintImpl>
void pretty_print(Message&& msg, const PrintImpl& print_impl)
{
    print_surrounded(std::forward<Message>(msg), "***", print_impl);
}

int main()
{
    pretty_print("So pretty!", [](const char* msg) {
        std::cout << msg;
    });
}

Я также разместил его на Coliru.

Как вы можете видеть, я использую разные способы передачи аргументов:

  • Сообщение передается как универсальная ссылка, потому что в конечном итоге его необходимо перенаправить в функцию PrintImpl.
  • Декорация передается как const ref здесь, потому что ее значение используется дважды, и я не уверен, что если использовать forward дважды, это будет безопасно. (Может быть, он ушел первым вперед?)
  • PrintImpl передается как ссылка на константу, потому что я не вижу причин для использования вперёд. Однако я не уверен, что это мудро. (Должен ли я проходить мимо &&? Если да, должен ли я также использовать std::forward?)

Я делаю правильный выбор?

Ответ 1

Я делаю правильный выбор?

Да (в основном).

Украшение записывается как const ref здесь, потому что его значение используется дважды, и я не уверен, что если использовать forward дважды, это будет безопасно. (Он может быть отодвинут первым вперед?)

Не используйте std::forward, когда вы делаете это несколько раз, именно по той причине, что вы выложили.

PrintImpl фиксируется как ссылка на константу, потому что я не вижу причин для использования вперёд.

Что вы можете сделать, это взять PrintImpl&& и не использовать std::forward (сохраняя их как lvalues), позволяя передавать объектные объекты без const -qualified operator().