gpt4 book ai didi

c++ - 使用 std::views 进行模板类型推断

转载 作者:行者123 更新时间:2023-12-02 18:26:29 25 4
gpt4 key购买 nike

我对函数式编程的了解有点晚了,并开始了解范围/ View 。我正在使用 MSVC19 并针对 C++ 20 进行编译。

我正在使用std::views::transform而且编译器似乎并没有像我天真的希望的那样推断类型。

这是一个小示例,它仅采用字符串 vector 并计算它们的长度:

#include <vector>
#include <iostream>
#include <ranges>

template<typename E>
auto length(const E& s)
{
std::cout << "Templated length()\n";
return static_cast<int>(s.length());
}

template<typename E>
auto getLengths(const std::vector<E>& v)
{
return v | std::views::transform(length<E>);
}

int main()
{
std::vector<std::string> vec = { "Larry","Curly","Moe" };
for (int i : getLengths(vec))
{
std::cout << i << "\n";
}
return 0;
}

输出:

Templated length()
5
Templated length()
5
Templated length()
3

我的问题是为什么要更改此行中的代码(删除 <E> ):

    return  v | std::views::transform(length);

给我一​​大堆错误,从: Error C2672 'operator __surrogate_func': no matching overloaded function found 开始?

为什么编译器没有推断出类型是 std::string如果我用非模板化函数替换模板:

auto length(const std::string& s) -> int
{
std::cout << "Specialized length()\n";
return static_cast<int>(s.length());
}

代码会编译并运行,因此显然没有模板,编译器会找到我正在使用的特定类型的匹配项。

最佳答案

这与 View 无关。您可以将问题简化为:

template <typename T>
int length(T const& x) { return x.length(); }

template <typename F>
void do_something(F&& f) {
// in theory use f to call something
}

void stuff() {
do_something(length); // error
}

C++ 并不真正进行类型推断。当你有 do_something(length) ,我们需要选择哪个 length我们正在谈论就在那里。我们不能这样做,所以这是一个错误。 do_something没有办法说“我想要用 std::string 调用的函数模板的实例化 - 完全取决于调用者提供 do_something 正确的东西。

原来的例子也是如此。 length<E>是一个具体的函数。 length不是你可以直接传入的东西。

典型的方法是通过将函数模板包装在 lambda 中来延迟实例化:

void stuff() {
do_something([](auto const& e) { return length(e); }); // ok
}

现在,这是可行的 - 因为 lambda 是一个表达式,其类型可以通过 do_something 推导出来。 ,而只是length不是。而且我们不必手动提供模板参数,这很容易出错。

我们可以用宏来概括这一点:

#define FWD(arg) static_cast<decltype(arg)&&>(arg)
#define LIFT(name) [&](auto&&... args) -> decltype(name(FWD(args)...)) { return name(FWD(args)...); }

void stuff() {
do_something(LIFT(length));
}

这避免了一些额外的输入,并且可能使意图更加清晰。

关于c++ - 使用 std::views 进行模板类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70086144/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com