【问题标题】:Current status of std::make_arraystd::make_array 的当前状态
【发布时间】:2018-06-20 07:25:54
【问题描述】:

std::make_array 提议的函数here 的当前状态如何?我找不到任何关于它可能被接受的信息。根据cppreference.com,它位于std::experimental 命名空间中。 C++ compiler supportWikipedia-C++17Wikipedia-C++20 和 C++17 标准草案中根本没有提到它。

【问题讨论】:

  • std::make_array 从 C++17 开始有点没用,不是吗?我们现在可以拥有std::array arr = { 1, 2, 3, 4, 5 };,而无需指定类型+大小。
  • @DeiDei - 在 C++17 中 - 我们只能省略数组大小吗?我的意思是 - 这可以帮助做这样的事情:auto a = std::make_array<int>(1, (float)1.2, 'x') - 希望编译器只计算大小 - 但不能使用推导指南,因为类型不同(但可以转换为所需的类型)
  • @PiotrNycz - 你也不能用std::make_array 做到这一点。您在包中指定了一种。其余的仍在推断和检查。
  • @StoryTeller 在示例中(在链接的提案中)我看到了这个:auto a2 = make_array<long>(2, 3U); // explicit destination type - 看起来 - 有可能吗?
  • @PiotrNycz - 提案使用std::common_type。仅当所需的目标类型 通用类型或更大的类型时,它才会起作用。你自己的尝试是行不通的,因为常见的类型是float,而不是int

标签: c++ arrays


【解决方案1】:

正如@DeiDei 所写,C++17 包含template argument deduction for classes,因此您现在可以编写:

std::pair p (foo, bar);
std::array arr = { 1, 2, 3, 4, 5 };

等等。但是还有一些(有些微妙的)剩余用例,make_pairmake_array 可能有用,您可以在以下位置阅读它们:Usefulness of std::make_pair and std::make_tuple in C++1z

@Ruslan 在评论中正确地指出,当元素的类型对编译器“显而易见”或对每个元素都明确时,上述内容最有用。如果你想显式构造某种类型的元素,上面的样子是这样的;

std::array arr = { MyType{1,2}, MyType{3,4}, MyType{5,6}, MyType{7,8} };

这太罗嗦了;这是您依赖的情况之一:

std::make_array<MyType>{ {1,2}, {3,4}, {5,6}, {7,8} };

【讨论】:

  • 这太酷了!不知道可以推导出std::array 的模板参数。谢谢!
  • value_type 没有内置时,这仍然不够好:例如你必须使用std::array arr={Type{1,3}, Type{7,2}, /*...,*/ Type{32,71}}; 而不是你写的auto arr=std::make_array&lt;Type&gt;({1,3}, {7,2}, /*...,*/ {32,71});,这对于更长的数组来说会更短。
  • make_array 的剩余用例不是被std::to_array 覆盖,用户可以显式声明数组元素的类型吗?!
  • @usr1234567:我的答案来自 2018 年,std::to_array 来自 C++2020...
【解决方案2】:

LEWG 投票支持将 merge paper 转发给 C++20 back in 2016(这是在 C++17 功能冻结之后)。应作者要求,其 LWG 审查暂停,等待LWG issue 2814 的决议。

【讨论】:

    【解决方案3】:

    answer 提供了提案的状态 - 但是 - 在 C++17 中很容易实现 - 至少这部分:

    [示例:

    int i = 1; int& ri = i;
    auto a1 = make_array(i, ri);         // a1 is of type array<int, 2>
    auto a2 = make_array(i, ri, 42L);    // a2 is of type array<long, 3>
    auto a3 = make_array<long>(i, ri);   // a3 is of type array<long, 2>
    auto a4 = make_array<long>();        // a4 is of type array<long, 0>
    auto a5 = make_array();              // ill-formed    auto a6 = make_array<double>(1, 2);  // ill-formed: might narrow –end example]
    

    见:

    template <typename Dest=void, typename ...Arg>
    constexpr auto make_array(Arg&& ...arg) {
       if constexpr (std::is_same<void,Dest>::value)
          return std::array<std::common_type_t<std::decay_t<Arg>...>, sizeof...(Arg)>{{ std::forward<Arg>(arg)... }};
       else
          return std::array<Dest, sizeof...(Arg)>{{ std::forward<Arg>(arg)... }};
    }
    

    证明:

    int main() {
        int i = 1; int& ri = i;
        auto a1 = make_array(i, ri);         // a1 is of type array<int, 2>
        std::cout << print<decltype(a1)>().get() << std::endl; 
        auto a2 = make_array(i, ri, 42L);    // a2 is of type array<long, 3>
        std::cout << print<decltype(a2)>().get() << std::endl;
        auto a3 = make_array<long>(i, ri);   // a3 is of type array<long, 2>
        std::cout << print<decltype(a3)>().get() << std::endl;
        auto a4 = make_array<long>();        // a4 is of type array<long, 0>
        std::cout << print<decltype(a4)>().get() << std::endl;
        // auto a5 = make_array();              // ill-formed
        // auto a6 = make_array<double>(1, 2);  // ill-formed: might narrow
    }
    

    输出:

    std::__1::array<int, 2ul>
    std::__1::array<long, 3ul>
    std::__1::array<long, 2ul>
    std::__1::array<long, 0ul>
    

    最后一行make_array&lt;double&gt;(1, 2) 产生“窄化”错误——正如提案中所要求的那样。它可以通过在实现中添加 static_cast 来“改进”。

    关于最新的 clang - demo

    【讨论】:

      【解决方案4】:

      现在有一个实验性的make_array

      https://en.cppreference.com/w/cpp/experimental/make_array

      在标题&lt;experimental/array&gt;中定义

      template &lt;class D = void, class... Types&gt; constexpr std::array&lt;VT /* see below */, sizeof...(Types)&gt; make_array(Types&amp;&amp;... t);

      (库基础 TS v2)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-06
        • 1970-01-01
        • 1970-01-01
        • 2020-06-14
        • 2020-08-14
        相关资源
        最近更新 更多