gpt4 book ai didi

c++ - 在 C++11 中,有没有一种方法可以在调用将任何可调用对象作为参数(包括绑定(bind)方法)作为参数的函数时不需要模板参数?

转载 作者:搜寻专家 更新时间:2023-10-31 01:33:50 25 4
gpt4 key购买 nike

为了拓宽我对 C++11 的理解,我正在尝试编写函数式助手,看看我是否可以让它们的调用不那么冗长。考虑以下代码:

#include <list>

int timesTwo(int x) { return x*2; }
int timesX(int x, int y) { return x*y; }

class Foo {
public:
Foo(int a) : value(a) {};
int fooTimesTwo() const { return value*2; };
int value;
};

template <class T, class U>
std::list<U> myMap(const std::list<T> &list, const std::function<U(const T &)> &func)
{
std::list<U> result;

for(typename std::list<T>::const_iterator it = list.begin(); it != list.end(); ++it) {
result.push_back(func(*it));
}

return result;
}

int main()
{
std::list<int> numbers = {1,2,3,4,5};
std::list<int> numbers2 = myMap<int,int>(numbers, [] (int x) { return x*2; });
std::list<int> numbers3 = myMap<int,int>(numbers, &timesTwo);
std::list<int> numbers4 = myMap<int,int>(numbers, std::bind(timesX, 2, std::placeholders::_1));

std::list<Foo> fooList = {Foo(1), Foo(2), Foo(3), Foo(4)};
std::list<int> numbers5 = myMap<Foo,int>(fooList, &Foo::fooTimesTwo);
return 0;
}

有没有办法重写 myMap 以便

  1. 我的代码示例中对它的所有四个调用都不需要任何模板参数,并且...

  2. 只有一个通用实现,我不必为我想调用它的每种类型组合手动编写重载版本?

我已经尝试将 myMap 的第二个参数更改为第三个模板类型而不是 std::function,但它失败了,因为 a) 第二个模板类型U 无法推断,并且 b) 即使可以,第四次调用 myMap 也会由于 &Foo::fooTimesTwo 而在第 20 行导致错误 不是函数或函数指针。

我愿意考虑 C++11 的所有不同特性来做到这一点,我并不特别关心它是否会使 myMap 的声明或定义变得迟钝或不可读。我只是想知道这是否可能,如果可能,什么样的技术和 C++11 功能可以实现它。

最佳答案

您可以尝试实现 std::invoke在 C++11 中,但我认为这真的很麻烦。

为通用可调用函数创建函数模板相当简单:

template <class T, class F>
auto myMap(const std::list<T> &list, F&& func)
-> std::list<typename std::decay<decltype(func(*list.begin()))>::type>
{
using U = typename std::decay<decltype(func(*list.begin()))>::type;
std::list<U> result;

for(typename std::list<T>::const_iterator it = list.begin(); it != list.end(); ++it) {
result.push_back(func(*it));
}

return result;
}

您可以免费获得 expression sfinae。现在只需要处理成员函数指针:

template <class T, class F>
auto myMap(const std::list<T> &list, F&& func)
-> std::list<typename std::decay<decltype(((*list.begin()).*func)())>::type>
{
return myMap(list, [=](T const& t){ return (t.*func)(); });
}

现在您可以按预期调用您的函数了。 demo


同时,您可以将这个丑陋的 for 循环替换为范围 for:

for(auto const& elem : list) {
results.push_back(func(elem));
}

或者使用算法:

std::transform(list.begin(), list.end(), std::back_inserter(result), func);

关于c++ - 在 C++11 中,有没有一种方法可以在调用将任何可调用对象作为参数(包括绑定(bind)方法)作为参数的函数时不需要模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40643797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com