Re: Perfect forwarding of default constructor?
bf wrote:
Unfortunately it fails if T isn't default constructible. A possible
solution can be made by defaulting the template parameter, instead of
an explicit default constructor.
template <typename T>
class wrapped
{
public:
template <typename U = T>
wrapped(U&& u = U()) : t(std::forward<U>(u) {}
private:
T t;
};
This allows default construction if T supports it, so logically it
works. In my experiments with g++, however, I see that the defaulted
value isn't optimized away. The move constructor for T is presumably
cheap, so it's probably not the end of the world, but it's
unnecessary. QOI detail, or behaviour mandated by proposed standard
wording?
I think a solution can be made with a variadic template constructor,
which also nicely takes care of multi-parameter constructors, but I
fail to figure out how to do a std::forward<U...>(u...). Suggestions?
_
Notice that a simple variadic constructor has bad behavior for overload
resolution:
void f(wrapped<int>);
void f(string);
// eww, ambiguous!
int main() { f("foo"); }
For inheriting constructors, this problem is solved by saying "using
base::base;". For forwarding data member constructors, you can use SFINAE
template <typename T>
class wrapped
{
public:
template <typename ...U,
typename = bool[is_constructible<T, U...>::value]>
wrapped(U&& ...u) : t(std::forward<U>(u)...) {}
private:
T t;
};
This still isn't perfect, as the following example shows:
void f(wrapped< vector<string> >);
void f(wrapped<int>);
int main() { f(42); } // ambiguous!
The "wrapped" constructor template is non-explicit, thus being available
both times and not SFINAE'ed out because vector has an explicit ctor taking
an int. is_constructible tells us that it will work. Of course if you were
to use it unwrapped, you could call "f" fine. Not only because 42 -> int
would be an exact match, but because "42 -> vector<string>" wouldn't be
possible in the first place.
If you aim for equivalence to the non-wrapped case, you have to simulate
copy-initialization and direct initialization distinction (explicit and non-
explicit constructors). I don't know whether that's possible at all. But i
can't see a real pressing need right now.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]