我可以实例化一个 std::reference_wrapper<T> ,其中 T 是不完整的类型吗?

Posted

技术标签:

【中文标题】我可以实例化一个 std::reference_wrapper<T> ,其中 T 是不完整的类型吗?【英文标题】:Can I instantiate an std::reference_wrapper<T> where T is an incomplete type? 【发布时间】:2014-11-20 12:55:50 【问题描述】:

std::reference_wrapper&lt;T&gt; 是否允许 T 不完整,就像在 T 不完整的情况下可以处理 T&amp; 一样?

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 的参数测试3

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

这些实现中的哪一个(如果有的话)遵循标准要求?

【问题讨论】:

我不知道,但我的赌注不在 MS 请注意,无论标准怎么说,MSVC 都会失败:This program 无法在 MSVC11+ 上编译,这要归功于 is_abstract 测试。 【参考方案1】:

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

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

2 特别是,在以下情况下效果是不确定的:

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

快速浏览 20.9.3 类模板reference_wrapper [refwrap] 发现reference_wrapper 没有这样的特定异常,因此您的程序具有未定义的行为。两种实现都符合要求。

【讨论】:

妈的,太慢了。 +1 BTW:我认为这是应该允许不完整类型的情况。 似乎唯一具有该特殊异常的组件是智能指针类型。我认为将它用于reference_wrapper 也很有意义,因为它很有用并且实现起来很简单(因为它通常只是指针的包装器,如智能指针)。整个不完整类型的问题是 C++ 标准中的一个非常薄弱的​​点(对于库组件和有关模板的规则),它需要更好的规范,例如更清晰的规则和所需的诊断/错误而不是 UB。 @Deduplicator 允许不完整类型的问题是reference_wrapper 必须遵守旧的unary_function/binary_function 协议以实现向后兼容性。为此,它需要根据模板参数的类型定义各种类型定义,例如[refwrap]/3:“模板实例化 ... 应将 ... argument_type 定义为 T1 的同义词,仅当类型 T 是以下任何一种时: ... 具有成员的类类型类型argument_type;类型T1T::argument_type。"。

以上是关于我可以实例化一个 std::reference_wrapper<T> ,其中 T 是不完整的类型吗?的主要内容,如果未能解决你的问题,请参考以下文章

我们可以直接实例化一个抽象类吗? [复制]

什么可以从元类实例化

可以使用类方法中的类名属性(在一行代码中)实例化 PHP 实例吗?

我可以检查哪些函数模板至少被实例化过一次吗?

阅读《实例化需求》1-3章有感

实例化一个对象,以便它可以与多个指令共享