【问题标题】:std::transform with an overloaded conversion function带有重载转换函数的 std::transform
【发布时间】:2021-03-04 15:12:20
【问题描述】:

我想从一个容器 c 转换所有对象 - 例如 char 类型,并将结果 - 类型为 foo - 存储在另一个容器 v 中。所需的转换函数是一个重载函数 - 称之为to_foo

考虑以下example

#include <algorithm>
#include <vector>    

struct foo {};

foo to_foo(char) { return {}; }
foo to_foo(int) { return {}; }

int main()
{
    std::array<char, 1> c;
    std::vector<foo> v(c.size());

//  cannot determine which instance of overloaded function "to_foo" is intended:
    std::transform(c.begin(), c.end(), v.begin(), to_foo);

//  ok:
    std::transform(c.begin(), c.end(), v.begin(), [](auto const& ch) { return to_foo(ch); });
}

虽然我认为在第一次转换中编译器不知道应该采用哪个 to_foo 重载(另一方面,他不能从迭代器的 value_type 中推断出它吗?) ,我不明白为什么他能够在第二次变换中这样做。这里发生了什么?

【问题讨论】:

    标签: c++ stl iterator c++17


    【解决方案1】:

    您必须通过强制转换 to_foo 来明确告诉它要使用哪个重载:

    std::transform(c.begin(), c.end(), v.begin(), static_cast<foo (*)(char)>(to_foo));
    

    std::transform 的一元操作参数的类型与用于迭代器的模板参数不同。所以它必须使用你传递的值的类型来推断模板参数。 to_foo 的类型不明确,因此无法完成该过程。将函数指针转换为特定的重载类型使其明确。


    在第二种形式中,lambda是一个可调用的对象,auto的使用使得该对象的()操作符成为一个函数模板:

    struct NamelessGenericLambda {
        template <typename T>
        foo operator ()(T const& ch) { return to_foo(ch); }
    };
    std::transform(c.begin(), c.end(), v.begin(), NamelessGenericLambda{});
    

    类型明确,可以实例化std::transform模板。

    然后在std::transform 的某个地方,它会尝试通过传递char 来实例化operator () 模板。因为它传递了一个明确的类型,所以编译器推断ch 是一个字符。然后它使用常规重载决议选择to_foo 的正确重载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-15
      • 2014-04-02
      • 1970-01-01
      • 2016-08-22
      • 1970-01-01
      • 2019-03-31
      • 1970-01-01
      • 2011-10-31
      相关资源
      最近更新 更多