来自signed int的std :: make_array <size_t>

时间:2017-01-22 19:56:12

标签: c++ arrays language-lawyer c++17

给出一个代码:

constexpr auto a = std::make_array<size_t>(1, 2, 3);

Clang(3.7)从GCC复制的实现libstdc++v3 experimental/array发出此警告:

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以接受上面给出的代码?

海湾合作委员会的实现:

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)...}};
  }

1 个答案:

答案 0 :(得分:3)

不,std::make_array不应与该构造相同。

std::make_array需要Types&&...,这需要从参数中确定类型,并在您的情况下生成类型为int的参数。在make_array内,您不再具有常量值,因此可以在{}内转换范围内常量整数值的例外不再适用。

另一个例子是std::array<void*, 1>{0}std::make_array<void*>(0)。前者是有效的,因为0可以转换为任何指针类型。后者无效,因为碰巧具有值0的整数参数不能隐式转换为任何指针类型。