它工作正常,但我希望它从函数的第二个参数中推断出 int 参数,因此能够编写:
for (auto i: map(&abs, li))
{
std::cout << i << std::endl;
}
问题是它abs
不是一个函数,而是一个函数模板,因此没有address-of abs
,尽管有&abs<int>
, 因为abs<int>
(specialization) 确实是一个函数(从模板生成)。
现在问题是您真正想要解决的问题,特别是您必须意识到 C++ 是一种静态类型的语言,而 python 是一种动态类型的语言。我不清楚你想在不同层面上实现什么。例如,python 中的函数在 C++map
中具有等效的in:std::transform
a = [ 1, 2, 3 ]
a = map(lambda x: 2*x, a)
std::vector<int> v{1,2,3};
std::transform(v.begin(),v.end(),v.begin(),[](int x){ return 2*x; });
我稍微作弊的地方是因为在 python 中它会创建一个不同的容器,而在 C++中它transform
在迭代器级别工作并且不知道容器,但是您可以类似地获得相同的效果:
std::vector<int> v{1,2,3};
std::vector<int> result;
// optionally: result.reserve(v.size());
std::transform(v.begin(),v.end(),
std::back_inserter(result),
[](int x) { return 2*x; });
我建议您学习该语言中的习语,而不是尝试使用其他语言的习语...
顺便说一句,如果您愿意让用户指定传递给map
函数的函子的类型,那么您可以只传递模板的名称并让编译器确定您需要什么专业化:
template <typename Container>
auto map(Container && c,
typename Container::value_type (*f)(typename Container::value_type))
-> MapObject<Callable<T>,Container>;
template <typename T>
T abs(T value);
int main() {
std::vector<int> v{1,2,3,4};
map(v,abs);
}
这不像您尝试做的那样通用,因为它只接受函数指针和具体类型(这std::transform
甚至abs
比&
.因此,对于专业化集合。然后它将使用预期的类型来选择一种特化并将其传入。&abs<int>
在这种情况下,编译器将为您隐式执行。
另一个更通用的替代方法是不使用函数,而是使用仿函数。考虑到这一点,您可以定义abs
为:
struct abs {
template <typename T>
T operator()(T t) { ...}
};
然后传递函子的副本而不是函数指针。无需确定在将对象传递给函数时使用的重载abs
,map
仅在使用时确定。调用方看起来像:
for (auto& element : map(container,abs()))
额外的一组括号是创建一个类型的对象abs
并将其传入。
总的来说,我会尽量避免这种情况。这是一件有趣的事情,您可能会找到一个好的解决方案,但这会很困难并且需要相当多的 c++ 专业知识。因为该语言不支持它,所以您必须设计一些在该语言中工作的东西,并且需要在不同的特性或语法上做出妥协。了解选项本身就是一个难题,更难理解折衷方案,更难找到好的解决方案。好的解决方案可能会比等效的惯用 C++ 代码更糟糕。
如果您使用 C++ 编程,请编写 C++。尝试通过 C++ 编译器编写Python代码可能会给您带来 C++ 的痛苦和 Python 的性能。