Можно ли создать экземпляр std:: reference_wrapper <T>, где T - неполный тип?

Разрешает ли std::reference_wrapper<T> T быть неполным, так же, как a T& можно обрабатывать без завершения T?

GCC 4.9 принимает следующее:

#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!)
}

Но MSVS 2012 отклоняет его со следующим сообщением:

Ошибка 1 ошибка C2139: 'woof': класс undefined не разрешен в качестве аргумента для атрибута встроенного типа компилятора '__is_abstract' c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits 755 1 тест3

Я подозреваю, что это потому, что op() нужен полный тип, но стандарт не указывает на какой-либо способ.

Что, если любая из этих реализаций соответствует стандартным мандатам?

Ответ 1

N3936 § 17.6.4.8 Другие функции [res.on.functions]:

1 В некоторых случаях (функции замены, функции обработчика, операции с типами, используемыми для создания стандартных компонентов шаблона библиотеки) стандартная библиотека С++ зависит от компонентов, предоставляемых программой на С++. Если эти компоненты не соответствуют их требованиям, Стандарт не устанавливает никаких требований к реализации.

2 В частности, эффекты undefined в следующих случаях:

  • ...
  • если неполный тип (3.9) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона, если специально не разрешено для этого компонента.

Быстрое сканирование через 20.9.3 Шаблон класса reference_wrapper [refwrap] не показывает такого конкретного исключения для reference_wrapper, поэтому ваша программа имеет поведение undefined. Обе реализации соответствуют.