为什么 `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>
,因为提案的作者认为这种用法 error-prone。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提案的措辞如下:
Ban reference_wrapper
in the make_tuple
-like interface. make_tuple
and make_pair
have special handling of reference_wrapper
, then user might expect that the expression
make_array(ref(a), ref(b))
also results in a tuple-like object storing T&
.
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>
,因为提案的作者认为这种用法 error-prone。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提案的措辞如下:
Ban
reference_wrapper
in themake_tuple
-like interface.make_tuple
andmake_pair
have special handling ofreference_wrapper
, then user might expect that the expressionmake_array(ref(a), ref(b))
also results in a tuple-like object storing
T&
.