首页 > 解决方案 > 带有重载转换函数的 std::transform

问题描述

我想char从一个容器中转换所有类型的对象(例如,类型)c并将结果(类型foo)存储在不同的容器中v。所需的转换函数是一个重载函数——调用它to_foo

考虑以下示例

#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++stliteratorc++17

解决方案


您必须通过强制转换明确告诉它要使用哪个重载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它内部的某个地方会尝试operator ()通过传递一个char. 因为它传递了一个明确的类型,所以编译器推断ch是一个字符。然后它选择to_foo使用常规重载决议的正确重载。


推荐阅读