Can I instantiate an std::reference_wrapper whe

2020-08-17 06:16发布

问题:

Does std::reference_wrapper<T> allow T to be incomplete, in the same way that a T& can be dealt with without T being complete?

GCC 4.9 accepts the following:

#include <functional>

struct woof;

struct test
{
   test(woof& w) : w(w) {}
   std::reference_wrapper<woof> w;
};

struct woof
{
   int a;
};

int main()
{
    woof w;
    test t = w;   // (braced-init would be better, but VS2012!)
}

But MSVS 2012 rejects it with the following message:

Error 1 error C2139: 'woof' : an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_abstract' c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits 755 1 test3

I suspect this is because the op() needs the full type, but the standard doesn't appear to specify either way.

Which, if either, of these implementations is following standard mandates?

回答1:

N3936 §17.6.4.8 Other functions [res.on.functions]:

1 In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

2 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.

A quick scan through 20.9.3 Class template reference_wrapper [refwrap] reveals no such specific exception for reference_wrapper, so your program has undefined behavior. Both implementations are conforming.