Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass template args by const& or &&

Tags:

c++

c++11

I have this example program:

#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;
    });
}

I also posted it on Coliru.

As you can see I use different ways to pass the arguments:

  • Message is passed as a universal reference because it eventually needs to be forwarded to the PrintImpl function.
  • Decoration is passed as const ref here because its value is used twice and I'm not sure if using forward twice would be safe. (It might be moved away by the first forward?)
  • PrintImpl is passed as const reference because I don't see any reason to use forward. However, I'm not certain if this is wise. (Should I pass by &&? If yes, should I also use std::forward?)

Am I making the right choices?

like image 824
StackedCrooked Avatar asked Jul 25 '13 09:07

StackedCrooked


1 Answers

Am I making the right choices?

Yes (mostly).

Decoration is captured as const ref here because its value is used twice and I'm not sure if using forward twice would be safe. (It might be moved away by the first forward?)

Don't use std::forward when you'd do it multiple times, exactly for the reason you layed out.

PrintImpl is captured as const reference because I don't see any reason to use forward.

What you might want to do is take PrintImpl&& and don't use std::forward (keeping them as lvalues), allowing function objects without const-qualified operator() to be passed.

like image 130
Xeo Avatar answered Oct 23 '22 20:10

Xeo