在 C++11 中,有没有一种方法可以在调用将任何可调用对象作为参数(包括绑定方法)作为参数的函数时不需要模板参数?
In C++11 is there a way to not require template arguments when calling a function that takes any callable as an argument, including bound methods?
为了拓宽我对 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, ×Two);
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
以便
我的代码示例中对它的所有四个调用都不需要任何模板参数,并且...
只有一个通用实现,我不必为我想调用它的每种类型组合手动编写重载版本?
我尝试将 myMap
的第二个参数更改为第三个模板类型而不是 std::function
,但它失败了,因为 a) 第二个模板类型 U
不能'无法推断,并且 b) 即使可以,第四次调用 myMap
也会导致第 20 行出现错误,因为 &Foo::fooTimesTwo
不是函数或函数指针。
我愿意考虑 C++11 的所有不同特性来做到这一点,我并不特别关心它是否会使 myMap
的声明或定义变得迟钝或不可读。我只是想知道这是否可能,如果可能,什么样的技术和 C++11 功能可以实现它。
您可以尝试在 C++11 中实现 std::invoke
,但我认为这会非常麻烦。
为广义可调用函数制作函数模板相当简单:
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(auto const& elem : list) {
results.push_back(func(elem));
}
或者使用算法:
std::transform(list.begin(), list.end(), std::back_inserter(result), func);
为了拓宽我对 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, ×Two);
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
以便
我的代码示例中对它的所有四个调用都不需要任何模板参数,并且...
只有一个通用实现,我不必为我想调用它的每种类型组合手动编写重载版本?
我尝试将 myMap
的第二个参数更改为第三个模板类型而不是 std::function
,但它失败了,因为 a) 第二个模板类型 U
不能'无法推断,并且 b) 即使可以,第四次调用 myMap
也会导致第 20 行出现错误,因为 &Foo::fooTimesTwo
不是函数或函数指针。
我愿意考虑 C++11 的所有不同特性来做到这一点,我并不特别关心它是否会使 myMap
的声明或定义变得迟钝或不可读。我只是想知道这是否可能,如果可能,什么样的技术和 C++11 功能可以实现它。
您可以尝试在 C++11 中实现 std::invoke
,但我认为这会非常麻烦。
为广义可调用函数制作函数模板相当简单:
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(auto const& elem : list) {
results.push_back(func(elem));
}
或者使用算法:
std::transform(list.begin(), list.end(), std::back_inserter(result), func);