Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I instantiate an std::reference_wrapper<T> where T is an incomplete type?

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?

like image 898
Lightness Races in Orbit Avatar asked Sep 25 '14 16:09

Lightness Races in Orbit


1 Answers

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.

like image 180
Casey Avatar answered Nov 15 '22 17:11

Casey