std::make_array<size_t> 来自 signed int
std::make_array<size_t> from signed int
给定一个代码:
constexpr auto a = std::make_array<size_t>(1, 2, 3);
具有从 GCC libstdc++v3 experimental/array 复制的实现的 Clang (3.7) 给出此警告:
error: non-constant-expression cannot be narrowed from type 'int' to 'value_type' (aka 'unsigned long') in initializer list [-Wc++11-narrowing]
return {{ std::forward<Types>(t)... }};
如果编译器在编译时知道 1、2 和 3 可以隐式转换为 size_t
,这是否合法?
当我写的时候它没有给出警告:
constexpr std::array<size_t, 3> a{1, 2, 3};
而std::make_array
应该和这个构造是一样的
理论多于实际问题。
额外问题:如何在 GCC 实现中更正 std::make_array
以接受上面给出的代码?
GCC的实现:
template <typename _Dest = void, typename... _Types>
constexpr auto
make_array(_Types&&... __t)
-> array<conditional_t<is_void_v<_Dest>,
common_type_t<_Types...>,
_Dest>,
sizeof...(_Types)>
{
static_assert(__or_<
__not_<is_void<_Dest>>,
__and_<__not_<__is_reference_wrapper<decay_t<_Types>>>...>>
::value,
"make_array cannot be used without an explicit target type "
"if any of the types given is a reference_wrapper");
return {{forward<_Types>(__t)...}};
}
不,std::make_array
不应该与该结构相同。
std::make_array
采用 Types&&...
,这需要根据参数确定类型,在您的情况下会生成 int
类型的参数。在 make_array
内,您不再有常量值,因此 in-range 常量整数值可以在 {}
内转换的例外情况不再适用。
另一个例子是 std::array<void*, 1>{0}
与 std::make_array<void*>(0)
。前者是有效的,因为 0
可以转换为任何指针类型。后者是无效的,因为恰好具有值 0
的整数参数不能隐式转换为任何指针类型。
给定一个代码:
constexpr auto a = std::make_array<size_t>(1, 2, 3);
具有从 GCC libstdc++v3 experimental/array 复制的实现的 Clang (3.7) 给出此警告:
error: non-constant-expression cannot be narrowed from type 'int' to 'value_type' (aka 'unsigned long') in initializer list [-Wc++11-narrowing]
return {{ std::forward<Types>(t)... }};
如果编译器在编译时知道 1、2 和 3 可以隐式转换为 size_t
,这是否合法?
当我写的时候它没有给出警告:
constexpr std::array<size_t, 3> a{1, 2, 3};
而std::make_array
应该和这个构造是一样的
理论多于实际问题。
额外问题:如何在 GCC 实现中更正 std::make_array
以接受上面给出的代码?
GCC的实现:
template <typename _Dest = void, typename... _Types>
constexpr auto
make_array(_Types&&... __t)
-> array<conditional_t<is_void_v<_Dest>,
common_type_t<_Types...>,
_Dest>,
sizeof...(_Types)>
{
static_assert(__or_<
__not_<is_void<_Dest>>,
__and_<__not_<__is_reference_wrapper<decay_t<_Types>>>...>>
::value,
"make_array cannot be used without an explicit target type "
"if any of the types given is a reference_wrapper");
return {{forward<_Types>(__t)...}};
}
不,std::make_array
不应该与该结构相同。
std::make_array
采用 Types&&...
,这需要根据参数确定类型,在您的情况下会生成 int
类型的参数。在 make_array
内,您不再有常量值,因此 in-range 常量整数值可以在 {}
内转换的例外情况不再适用。
另一个例子是 std::array<void*, 1>{0}
与 std::make_array<void*>(0)
。前者是有效的,因为 0
可以转换为任何指针类型。后者是无效的,因为恰好具有值 0
的整数参数不能隐式转换为任何指针类型。