2012/12/12 Fernando Pelliccioni <
fpelli...@gmail.com>:
> Hi all,
>
> Is the following code valid ?
I don't think so.
> struct A;
>
> struct B
> {
> B(A& a) : a_(a) {}
> std::reference_wrapper<A> a_;
> };
>
> struct A
> {
> };
>
> According to the Standard, for reference_wrapper<T>, Is it allowed that T be
> an incomplete type?
No. std::reference_wrapper does not have an explicit statement for
this, therefore
the general rule [res.on.functions] p2:
"In particular, the effects are undefined in the following cases:
[..]
— if an incomplete type (3.9) is used as a template argument when
instantiating a template component,
unless specifically allowed for that component."
applies.
> From what I see, it is not explicitly stated in the Standard. On the
> contrary, for shared_ptr<T> is explicitly stated.
Yes, this is intended here (also for unique_ptr for non-arrays, btw.).
> Does the Standard allows references to incomplete types?
Sure.
> Is the following code valid ?
>
> struct A;
>
> struct B
> {
> B(A& a) : a_(a) {}
> A& a_;
> };
>
> struct A
> {
> };
This is valid, yes.
> Do you consider it right to allow that T to be incomplete for
> reference_wrapper<T> ?
For most parts of the type specification an incomplete type could work.
Of-course you would need to add extra wording in regard to the instantiation of
the operator() overload.
One more serious problem (because it effects the whole template
instantiation and not a single member) are the implications of
[refwrap] p3 b3:
"The template instantiation reference_wrapper<T> shall define a nested
type named argument_type as a
synonym for T1 only if the type T is any of the following:
[..]
— a class type with a member type argument_type; the type T1 is
T::argument_type."
Assume that the previous two bullets (T is a function type or pointer
thereof or a pointer to member) do not apply. Now if T is incomplete,
the type described here cannot be determined. It might exist or might
not. So, when T is incomplete the member type does not exist. But when
T is completed, a following instantiation would give a
reference_wrapper that has such a type. This is a clear violation of
the ODR and thus UB.
The same problem arises via the weak result type described in p2 and
the potential member types first_argument_type and
second_argument_type described in p4.
- Daniel