问题 我可以实例化一个std :: reference_wrapper ,其中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':不允许将未定义的类作为编译器内部类型特征的参数'__is_abstract'c:\ program files(x86)\ microsoft visual studio 11.0 \ vc \ include \ type_traits 755 1 test3

我怀疑这是因为 op() 需要完整类型,但标准不需要 出现 指定任一方式。

这些实现中的哪一个符合标准要求?


6286
2017-09-25 16:44


起源

我不知道,但我的赌注不在MS上 - Neil Kirk
请注意,无论标准是什么,MSVC都会失败: 这个计划 不能在MSVC11 +上编译,多亏了 is_abstract 测试。 - Xeo


答案:


N3936§17.6.4.8其他功能[res.on.functions]

1在某些情况下(替换函数,处理函数,用于实例化标准库模板组件的类型的操作),C ++标准库依赖于C ++程序提供的组件。如果这些组件不符合要求,则标准对实施没有要求。

2特别是,在下列情况下,效果未定义:

  • ...
  • 如果在实例化模板组件时将不完整类型(3.9)用作模板参数,   除非特别允许该组件。

快速浏览 20.9.3类模板 reference_wrapper [refwrap] 没有透露具体的例外情况 reference_wrapper,所以你的程序有不确定的行为。两种实现都是一致的。


15
2017-09-25 17:00



该死的,太慢了。 +1 BTW:我认为这是一个允许不完整类型的情况。 - Deduplicator
似乎唯一具有该特殊异常的组件是智能指针类型。我觉得拥有它会很有意义 reference_wrapper 因为它可能很有用而且很容易实现(因为它通常只是一个指针的包装器,如智能指针)。整个不完整类型的问题是C ++标准中的一个非常弱点(包括库组件和模板规则),它需要更好的规范,比如更清晰的规则和所需的诊断/错误而不是UB。 - Mikael Persson
@Deduplicator允许不完整类型的问题是 reference_wrapper 必须遵守旧的 unary_function/binary_function 向后兼容性协议。为此,它需要基于模板参数的类型定义各种typedef,例如, [refwrap] / 3:“模板实例化......应该定义...... argument_type 作为的同义词 T1 只有类型 T 是以下任何一种:...具有成员类型的类类型 argument_type;方式 T1 是 T::argument_type“。 - Casey