Reputation: 510
Perfect forwarding is usually seen in the context of template classes. For a non-template class, is it worth making e.g. the constructor a template method so it can use perfect forwarding? Something like the below:
class Foo()
{
public:
template<typename T>
Foo(T &&vec) : memberVec(std::forward<T>(vec)) {};
private:
std::vector memberVec;
};
The advantages are fundamentally the same, but is anything different when we know the real class type? When would this be good practice and when not?
Upvotes: 4
Views: 432
Reputation: 275260
A non-explicit one-argument ctor is a converting ctor. Unless Foo
should be convertible-from a vector (which might be true), you should make it explicit
.
In general, with one-argument ctors you need to SFINAE-disable Foo
types from being matched. The implicit Foo&&
and Foo const&
ctors are worse matches when you invoke Foo
with a Foo&
(say, an non-const lvalue) than your template ctor. A simple class=std::enable_if_t<!std::is_same<std::decay_t<T>,Foo>>
suffices.
Slightly more code will be generated.
In this case, std::vector<X>
is ridiculously cheap to move, so
Foo( std::vector<X> vec ):memberVec(std::move(vec)) {}
is 99% as efficient and clearer.
The usual perfect forwarding failures apply when you use it. The above example doesn't have them -- I can Foo x({1,2,3})
and it passes {1,2,3}
to construct the vec
. With T&&
it won't, because it cannot deduce what T
is.
Upvotes: 5