[英]How can std::reference_wrapper<int> use operator+= if std::reference_wrapper doesn't have operator+=?
[英]Why can't `std::experimental::make_array` use `std::reference_wrapper`?
template <class D, class...>
struct return_type_helper
{
using type = D;
};
template <class... Types>
struct return_type_helper<void, Types...> : std::common_type<Types...>
{
static_assert(
// why can't I use reference wrappers?
std::conjunction_v<not_ref_wrapper<Types>...>,
"Types cannot contain reference_wrappers when D is void"
);
};
template <class D = void, class... Types>
constexpr std::array<typename return_type_helper<D, Types...>::type, sizeof...(Types)> make_array(Types&&... t)
{
return {std::forward<Types>(t)...};
}
void foo()
{
int x = 7355608;
auto arr = make_array(std::ref(x)); // does not compile
}
为什么std::experimental::make_array()
有一个static_assert()
不允许在自动推导数组类型时使用std::reference_wrapper
? 创建一个引用包装器数组在其他方面是完全合法的,也就是说编译器没有问题
auto arr2 = std::array<decltype(std::ref(x)),1>{std::ref(x)};
检查提案N3824证实了我最初的怀疑。
即,添加了static_assert
检查以明确禁止从make_array
中推导std::array<std::reference_wrapper<T>, N>
类型,因为提案的作者认为这种用法容易出错。 1个
也就是说,使用以下代码:
auto x = 42;
auto a = make_array(std::ref(x));
用户可以合理地期望a
的类型为std::array<int&, 1>
,因为std::ref
在其他上下文中的行为类似。
实际上std::array<int&, 1>
没有命名有效类型并且无法构造,因此这种混淆的危险很小。 尽管如此,作者还是发现在这里谨慎行事是值得的,并使 API 具有最大的防御性。
因此,如果用户想要创建一个引用包装器数组,他们需要显式请求该类型:
auto a = make_array<std::reference_wrapper<int>>(std::ref(x));
1这是提案的措辞:
在
make_tuple
的界面中禁止reference_wrapper
。make_tuple
和make_pair
对reference_wrapper
有特殊处理,那么用户可能期望表达式make_array(ref(a), ref(b))
还会导致类似元组的 object 存储
T&
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.