繁体   English   中英

为什么 std::experimental::make_array 不能使用 std::reference_wrapper?

[英]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_tuplemake_pairreference_wrapper有特殊处理,那么用户可能期望表达式

make_array(ref(a), ref(b))

还会导致类似元组的 object 存储T&

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM