简体   繁体   English

将 std::array 传递给期望 std::span 的 function 时减少范围

[英]Deducing extent when passing std::array to function expecting std::span

I have a function expecting a std::span parameter.我有一个 function 期待一个std::span参数。 This function is called by passing an std::array .这个 function 通过传递一个std::array来调用。 This works fine if the std::span argument is declared with template parameter Extent set to std::dynamic_extent .如果std::span参数使用设置为std::dynamic_extent的模板参数Extent声明,则此方法工作正常。 But if the function is templated on Extent , the compiler is unable to deduce this value from std::array argument.但是如果 function 在Extent上被模板化,编译器就无法从std::array参数中推断出这个值。

Any idea why the compiler is unable to deduce this template argument?知道为什么编译器无法推断出这个模板参数吗?

See the snippet code below ( Godbolt link ).请参阅下面的代码片段( Godbolt 链接)。

Update after comments评论后更新

When we explicitly create a std::span ( without specifying template parameters ) object when calling g() , everything works fine, the compiler is able to deduce the span type and Extent from the std::array .当我们在调用g()时显式创建std::span不指定模板参数) object 时,一切正常,编译器能够从std::array推断出跨度类型和Extent Following cppreference , the corresponding constructor (5) is not mark as explicit .cppreference之后,相应的构造函数 (5) 未标记为explicit

So why is the compiler unable to do the same deduction?那么为什么编译器不能做同样的推论呢?

void f(const std::span<std::byte> buffer)
{
    std::cout << "f() => Extent = 0x" << std::hex << buffer.extent
              << " Size = " << std::dec << buffer.size() << std::endl;
}

template<std::size_t Extent>
void g(const std::span<std::byte, Extent> buffer)
{
    std::cout << "g() => Extent = 0x" << std::hex << buffer.extent
              << " Size = " << std::dec << buffer.size() << std::endl;
}

std::array<std::byte, 4> buffer = {};

f(buffer);
g(std::span{buffer}); // <= Works fine
g(buffer);            // <= Compiler error!

With this result from compiler:使用编译器的这个结果:

<source>:23:6: error: no matching function for call to 'g(std::array<std::byte, 4>&)'
   23 |     g(buffer);
      |     ~^~~~~~~~
<source>:13:6: note: candidate: 'template<long unsigned int Extent> void g(std::span<std::byte, _Count>)'
   13 | void g(const std::span<std::byte, Extent> buffer)
      |      ^
<source>:13:6: note:   template argument deduction/substitution failed:
<source>:23:6: note:   'std::array<std::byte, 4>' is not derived from 'std::span<std::byte, _Count>'
   23 |     g(buffer);
      |     ~^~~~~~~~

So why is the compiler unable to do the same deduction?那么为什么编译器不能做同样的推论呢?

Because class template argument deduction is a different process from function template argument deduction.因为 class 模板参数推导是与function模板参数推导不同的过程。

In the case of g , the compiler has no idea what the constructors of span are because... it's not a class yet.g的情况下,编译器不知道span的构造函数是什么,因为......它还不是 class 。 It's a template .这是一个模板 And since template specialization is a thing, it is entirely possible that the deduced Extent value radically changes what span conversion constructors are available.并且由于模板专业化是一件事,因此推断的Extent值完全有可能从根本上改变可用的span转换构造函数。

Function template argument deduction is about matching the type of each function argument against the type and template parameters of the corresponding parameter type. Function 模板实参推导是将每个 function 实参的类型与对应的形参类型的类型和模板形参进行匹配。 Since you're using a specific template type whose arguments have to be deduced from those of the incoming parameter, this requires that the parameter be a specialization of that template.由于您使用的是特定模板类型,其 arguments 必须从传入参数的那些推导出来,这要求参数是该模板的特化。

Class template argument deduction bypasses all of this because it is solely based on the constructor declarations in the primary template (and any template deduction guides). Class 模板参数推导绕过了所有这些,因为它基于主模板中的构造函数声明(以及任何模板推导指南)。 It can use the constructors in that template to deduce the template parameters.它可以使用该模板中的构造函数来推断模板参数。

But function template argument deduction doesn't work that way.但是 function 模板参数推导不是这样。

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

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