【问题标题】:std::make_array<size_t> from signed int来自有符号整数的 std::make_array<size_t>
【发布时间】:2017-01-22 19:56:11
【问题描述】:

给定一个代码:

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 是标准规定的,还是实现的结果?
    • @vladon 这是this proposal to add it 的要求,但我不确定这是否是最新的描述。
    • 如果有帮助,目前的措辞来自N4617 §9.2.2 和P0325
    • @ildjarn 这表明添加了一个示例,特别指出了此处的 OP 所询问的问题,因此感谢您的链接:)
    猜你喜欢
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 2014-03-11
    • 2011-06-06
    • 2020-05-06
    • 2010-09-19
    • 2013-10-02
    相关资源
    最近更新 更多