函子未被识别为transform_view args

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

在我看来,我有这样的心理模型,认为这两个表达是同义词

R | std::views::transform([](auto&& e) { return f(e); });    
R | std::views::transform(f); // good, saves unnecessary lambda

但是我有一个反例godbolt

#include <generator>
#include <map>
#include <ranges>

std::generator<int> to_prime_factors(int x) {
    for (int i = 2; i < x; ++i) {
        while (x % i == 0) {
            co_yield i;
            x /= i;
        }
    }

    if (x > 1) {
        co_yield x;
    }
}

template <std::ranges::input_range R>
std::map<std::ranges::range_value_t<R>, int> to_counter(R&& range) {
    std::map<std::ranges::range_value_t<R>, int> counter;
    for (auto&& ele : range) {
        counter[ele]++;
    }

    return counter;
}

int main() {
    static_assert(
        std::same_as<int, std::ranges::range_value_t<std::generator<int>>>);

    auto as = std::views::iota(2, 6);

    as | std::views::transform(to_prime_factors) |
        std::views::transform([](auto&& factors) {
            static_assert(std::ranges::input_range<decltype(factors)>);
            return to_counter(factors); // stinky unnecessary lambda
        });

    as | std::views::transform(to_prime_factors) |
        std::views::transform(to_counter); // oops

    return 0;
}

从 GCC 日志中可以看出,它无法将最后一个表达式识别为部分适配器, 因为数量不匹配,但它也表明

Args = {}
这与我的期望不符,因为我已经通过了
to_counter

问题:

  • 为什么包装一个简单转发 lambda 会给出不同的编译结果
  • 为什么 GCC 忽略
    to_counter
    作为
    transform_view
    的参数?
c++ functor std-ranges
1个回答
0
投票

你这么认为

[](auto&& e) { return f(e); }

是多余的,但实际上很有用。它允许

f
不一定是函子,而是许多其他东西,包括一组重载函数、函数模板或命名空间 std 中的函数(C++ 标准禁止直接使用它来代替函子)。

虽然你的问题以“函子无法识别......”开头,但

to_counter
不是函子,甚至不是函数 - 它是一个函数模板。您可以用真正的函子替换
to_counter
的定义,即使用包含泛型
operator()
的类型的对象 - 然后一切都会编译:

inline struct {
    template <std::ranges::input_range R>
    std::map<std::ranges::range_value_t<R>, int> operator()(R&& range) {
        std::map<std::ranges::range_value_t<R>, int> counter;
        for (auto&& ele : range) {
            counter[ele]++;
        }

        return counter;
    }
} to_counter{};
© www.soinside.com 2019 - 2024. All rights reserved.