Re: Perfect forwarding of default constructor?
On Jul 14, 5:48 pm, bf <bjor...@fahller.se> wrote:
QOI detail, or behaviour mandated by proposed standard
wording?
I ask myself that sort of question quite often. I'm not sure what the
answer when side-effects are present in either the constructor(s) and
destructor. Obviously under the as-if rule an implementation is free
to sort those details out but from what I know of compiler technology
and static analysis this can be tricky for non-trivial constructors/
destructors.
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?
I typically write a perfect forwarding constructor thus:
template<typename ...U>
some_type(U&& ...u): some_member(std::forward<U>(u)...) {}
Which is, incidentally, what appears in papers for the next standard I
believe. The trick (well, for me anyway) is to write as if the
template were not variadic, and adding ...'s in such a fashion that it
is factored out the furthest. My latest attempt was "variading" the
following:
template<typename T>
struct {
boost::variant<
std::future<T>*,
T
> f;
};
to:
template<typename ...T>
struct {
boost::variant<
std::future<T>*,
T
...> f;
};
Note also that under gcc-4.5 a variadic, perfect-forwarding
constructor will mess copy construction two-fold:
- a custom-defined constructor suppress the default instantiation of
the copy constructor
This is obvious but if you forget it you might not notice it if the
perfectly-forwarded call is valid construct!
The obvious cure is adding the default copy constructor:
some_type(some_type const&) = default; (you can put in delete instead
if your type is non-copyable and you want a more explicit warning when
someone attempts to copy)
- the perfect-forwarding constructor eats reference to non-const.
D'oh !
So assuming you do have a copy constructor:
some_type s;
auto const& cr = s;
some_type(cr); // fine!
some_type(s); // Uh oh! some_type(U&& ...u) gets called with U =
some_typ&!
I don't know if this is intended by the standard or a quirk of gcc-4.5
(rvalue refs 1.0 got redesigned for this kind of gotcha's I believe,
but much worse). I've had some luck disabling that sort of behaviour
with std::enable_if and std::is_same (from <type_traits>) but I'm not
that familiar with template metaprogramming so I don't think I've done
it for _variadic_ perfect-forwarding constructors.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]