std::transform 具有重载的转换函数
std::transform with an overloaded conversion function
我想从一个容器 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
的迭代器?),我不明白为什么他能够在第二次转换中这样做。这里发生了什么?
你必须通过强制转换 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
的正确重载。
我想从一个容器 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
的迭代器?),我不明白为什么他能够在第二次转换中这样做。这里发生了什么?
你必须通过强制转换 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
的正确重载。