我可以实例化一个 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<T>
是否允许 T
不完整,就像在 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 的参数测试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
;类型T1
是T::argument_type
。"。以上是关于我可以实例化一个 std::reference_wrapper<T> ,其中 T 是不完整的类型吗?的主要内容,如果未能解决你的问题,请参考以下文章