简体   繁体   English

推断 std::array 大小?

[英]Deduce std::array size?

In the following code:在以下代码中:

template<size_t N>
int b(int q, const std::array<int, N>& types)
{
    int r = q;
    for (int t : types)
    {
        r = r + t;
    }
    return r;
}

int main()
{
    b<2>(9, { 2,3 });
}

How can I avoid having to specify 2 in the call to b for N?如何避免在为 N 调用 b 时必须指定 2? Why can't this type be automatically deduced?为什么不能自动推导出这种类型? With out it I get the error:没有它我得到错误:

'b': no matching overloaded function found 'int b(int,const std::array &)': could not deduce template argument for 'N' “b”:没有匹配重载 function 找到“int b(int,const std::array &)”:无法推断“N”的模板参数

C++17 std::array class template argument deduction (CTAD) C++17 std::array类模板参数推导(CTAD)

Starting with C++17, this new language feature is now used by the standard library and now allows us to omit the template types as well so that the following works:从 C++17 开始, 这个新的语言特性现在被标准库使用,现在允许我们省略模板类型,以便以下工作:

main.cpp主程序

#include <array>

int main() {
    std::array a{1, 2, 3};
}

instead of std::array<int, 3> a{1, 2, 3};而不是std::array<int, 3> a{1, 2, 3};

Tested with:测试:

g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp

If we set -std=c++14 instead for example, it fails to compile with:例如,如果我们设置-std=c++14 ,它将无法编译:

error: missing template arguments before ‘a’

Tested on Ubuntu 18.04, GCC 7.5.0.在 Ubuntu 18.04、GCC 7.5.0 上测试。

Template argument deduction relies on direct type matching between actual argument and formal argument.模板参数推导依赖于实际参数和形式参数之间的直接类型匹配。 The actual argument is an initializer list.实际参数是一个初始化列表。 It doesn't match the array type (at best it could match the internal raw array in a std::array , but the language rules don't support that).它与array类型不匹配(充其量它可以匹配std::array中的内部原始std::array ,但语言规则不支持)。

Instead you can just use a raw array, to wit:相反,您可以只使用原始数组,即:

#include <stddef.h>
#include <array>

template<size_t N>
int b(int q, int const (&types)[N] )
{
    int r = q;
    for (int t : types)
    {
        r = r + t;
    }
    return r;
}

int main()
{
    b( 9, { 2, 3 } );
}

Or, if you don't absolutely need N at compile time, you can use a std::initializer_list .或者,如果您在编译时不是绝对需要N ,则可以使用std::initializer_list

There are also many other possibly relevant approaches (eg variadic template function, or defining an operator to build up a std::vector ), but it's difficult to say what would suit your undisclosed purpose.还有许多其他可能相关的方法(例如可变参数模板函数,或定义一个运算符来构建std::vector ),但很难说哪种方法适合您未公开的目的。

For deducing std::array size you can use generic lambdas (C++14):要推导出std::array大小,您可以使用通用 lambdas (C++14):

auto b = [](int q, const auto& types) {
  int r = q;
  for (int t : types)
  {
      r = r + t;
  }
  return r;
};

int main() {
    std::array<int, 2> arr = {{2,3}};
    b(9, arr);
}

When std::make_array (it's in Library Fundamentals TS) will get implemented by compilers (or you will use some own implementation of it) you won't also need to pass array size when constructing, just usestd::make_array (它在库基础 TS 中)将由编译器实现(或者您将使用它的一些自己的实现)时,您在构造时也不需要传递数组大小,只需使用

b(9, std::make_array(2,3));

Since C++20 we can use std::to_array() for type and size deduction.从 C++20 开始,我们可以使用std::to_array()进行类型和大小推导。

In your case:在你的情况下:

int b(int q, const auto& types)
{
    int r = q;
    for (int t : types)
    {
        r = r + t;
    }
    return r;
}

b(9, std::to_array({2, 3}));
// --- or ---
b(9, std::to_array<int>({2, 3}));

Personally I prefer std::span (or gsl::span ) in function parameters.我个人更喜欢 function 参数中的std::span (或gsl::span )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM