C++ 中 std::span 的模板类型推导失败

问题描述 投票:0回答:1

我正在 C++ 中使用模板和类型推导,并在使用 std::span 但不使用原始指针时遇到类型推导失败。下面是我的代码的简化版本:

#include <span>
#include <vector>

template <typename T>
void f1(std::span<const T> param)
{}

template <typename T>
void f2(const T* param)
{}

int main()
{
   std::vector<int> v{1,2,3};
   std::span<int> s{v};
   // f1(s); // Uncommenting this line causes a compilation error: cannot deduce a type for 'T' that would make 'const T' equal 'int'
   int x = 10;
   int* px = &x;
   const int* z = px;
   f2(px); // Works fine
   f2(z);  // Works fine
}

当我取消注释 f1(s) 调用时,我收到一条编译错误,指出编译器无法推导出“T”的类型,从而使“const T”等于“int”。然而,类似的指针模板函数(如 f2)在传递 int* 和 const int* 时编译不会出现任何问题。

为什么 std::span 会出现此错误,而指针则不会?

c++ templates type-deduction std-span
1个回答
0
投票

std::span<T>
可以隐式转换为
std::span<const T>
。因此,如果函数中的
T
int
,则您的
std::span<int>
参数可以转换为函数所需的
std::span<const int>
。然而,这并不意味着编译器能够在其模板参数推导过程中弄清楚这一点。

编译器的模板参数推导过程并不关心什么可以转换成什么。它需要

T
的一些参数,以便
std::span<const T>
std::span<int>
相同,正如错误消息中所说,没有参数,因为没有。如果
T
是一个
int
,正如我上面所说,
std::span<const T>
将是一个
std::span<const int>
,可以从
std::span<int>
隐式转换。 但它仍然不是编译器想要的完全相同的类型,因此该选项被排除在外。

您可以通过两种方式解决此问题:

  • 显式指定模板参数。所以,
    f1<int>(s)
    而不是
    f1(s)
    。这避免了任何模板参数推导。
  • 或者,保留模板参数推导,并将
    s
    变为
    std::span<const int>
    ,而不是像当前那样成为
    std::span<int>
    。现在确实存在一个类型
    T
    ,使得
    std::span<const T>
    std::span<const int>
    ,并且编译器将正确识别并使用它。
© www.soinside.com 2019 - 2024. All rights reserved.