Question

I want to develop a small polymorphic class with type erasure and I wonder which version of the templatized constructor is better and should be used.

We can pass by value:

class A
{
    ...
    template< typename T >
    A( T t ) { /* create the underlying model via std::move */ }
    ...
};

or we can use a universal reference:

class A
{
    ...
    template< typename T >
    A( T &&t ) { /* create the underlying model via std::forward */ }
    ...
};

(The universal reference has to be enabled if for the case that T is not the class itself and the class is not copied). Any ideas? Both version look equal to me.

Was it helpful?

Solution

These are not equivalent and sometimes one is desired over the the other one. A stellar talk by Nicolai Josuttis is an hour worth of talking just about this. I highly recommend watching it at least once.

Personally, unless you encounter a special case, where conversions are expensive and you want to avoid temporaries as much as possible, I would suggest just passing by value and std::moveing the argument.

Case where T&& is more efficient:

struct foo {
    std::string bar;

    template <typename T>
    foo(T&& t)
        :bar(std::forward<T>(t)){}
};

versus:

struct foo {
    std::string bar;

    foo(std::string t)
        :bar(std::move(t)){}
};

when you do:

int main() {
    foo f("some char*");
}

In the first case (perfect forwarding) you simply construct a std::string with const char* argument. In the second case, you construct one temporary (t from "some char*") and one empty std::string object, then you apply one move operation. It's not the end of the world, but the first version is simply more efficient.

To be absolutely clear about performance:

  • The first version uses 1 allocation

  • the second version uses 1 allocation and 1 move

and by move I don't mean std::move, since it generates no code (it's just a cast). By move I mean the code that needs to be execuded that actually moves from the string, which is a part of std::string(std::string&&).

Once again - the above example was based on the talk I linked at the beginning of the answer. It's really worth watching.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top