我经常在互联网上看到各种各样的抱怨,其他人的currying例子并不是currying,但实际上只是部分应用.
我没有找到关于部分应用是什么的合理解释,或者它与currying有何不同.似乎存在普遍的混淆,在某些地方将等效的例子描述为currying,在其他地方描述为部分应用.
有人可以向我提供这两个术语的定义,以及它们如何区别的细节吗?
language-agnostic terminology definition currying partial-application
我正在尝试存储std::tuple
不同数量的值,这些值稍后将用作调用与存储类型匹配的函数指针的参数.
我创建了一个简化的示例,显示了我正在努力解决的问题:
#include <iostream>
#include <tuple>
void f(int a, double b, void* c) {
std::cout << a << ":" << b << ":" << c << std::endl;
}
template <typename ...Args>
struct save_it_for_later {
std::tuple<Args...> params;
void (*func)(Args...);
void delayed_dispatch() {
// How can I "unpack" params to call func?
func(std::get<0>(params), std::get<1>(params), std::get<2>(params));
// But I *really* don't want to write 20 versions of dispatch so I'd rather
// write something like:
func(params...); // Not legal
}
}; …
Run Code Online (Sandbox Code Playgroud) c++ function-pointers variadic-templates c++11 iterable-unpacking
在某些情况下,希望能够键入 - 擦除可调用的(例如函数,函数指针,带有operator()
lambda的对象实例mem_fn
),例如在使用带有C++ 11 lambdas的Boost适配器中,其中可复制的和可默认构造的类型是必需的.
std::function
将是理想的,但似乎没有办法自动确定用于实例化类模板的签名std::function
.是否有一种简单的方法来获取任意可调用的函数签名和/或将其包装在适当的std::function
实例化实例(即make_function
函数模板)中?
具体来说,我正在寻找一个或另一个
template<typename F> using get_signature = ...;
template<typename F> std::function<get_signature<F>> make_function(F &&f) { ... }
Run Code Online (Sandbox Code Playgroud)
这样make_function([](int i) { return 0; })
返回std::function<int(int)>
.显然,如果一个实例可以使用多个签名(例如,具有多个,模板或默认参数operator()
的对象)进行调用,那么预计这不会起作用.
尽管非过度复杂的非Boost解决方案是优选的,但Boost很好.
编辑:回答我自己的问题.
据我所知,所有数据类型必须在编译时知道,而lambda不是一个类型.lambda被翻译成anonymous struct with operator()
或std::function
包裹?
例如,
std::for_each(v.begin(), v.end(), [](int n&){n++;});
Run Code Online (Sandbox Code Playgroud) 一直以来,我发现自己做了这样的事情:
Animal *animal = ...
if (Cat *cat = dynamic_cast<Cat *>(animal)) {
...
}
else if (Dog *dog = dynamic_cast<Dog *>(animal)) {
...
}
else { assert(false); }
Run Code Online (Sandbox Code Playgroud)
一旦我看到C++ 11中的闭包,我想知道,这样的事情可能吗?
Animal *animal = ...
typecase(animal,
[](Cat *cat) {
...
},
[](Dog *dog) {
...
});
Run Code Online (Sandbox Code Playgroud)
实现类型规划本来应该很容易,但我一直遇到一个问题,它无法弄清楚函数的参数,所以它无法知道尝试使用dynamic_cast,因为很难推断出lambdas的参数.花了几天的时间搜索谷歌和SO,但终于想通了,所以我将在下面分享我的答案.
我有一个数字列表.
我试图过滤列表,只保留正数.
我试图通过传递lambda作为参数来做到这一点.
我想知道为什么我会出现函数不匹配错误.
#include <vector>
#include <algorithm>
#include <functional>
template<typename T>
std::vector<T> keep(
const std::vector<T> &original,
std::function<bool(const T&)> useful)
{
std::vector<T> out;
for(T item:original)
{
if(useful(item))
out.push_back(item);
}
return out;
}
int main()
{
std::vector<int> a={4,6,2,-5,3,-8,13,-11,27};
a=keep(a,[](const int& x)->bool{return x>0;});
for(int y:a)
{
std::cout<<y<<std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
error: no matching function for call to ‘keep(std::vector<int>&, main()::<lambda(const int&)>)’
a=keep(a,[](const int& x)->bool{return x>0;});
^
Run Code Online (Sandbox Code Playgroud) 我正在研究多种类型的地图持有者.它适用于所有原始类型,也适用于结构,例如Point.但是,如果我想将std :: function添加为另一个受支持的类型(用于回调),那么编译器会抱怨:
MT.cpp:426:15:没有可行的重载'='
MT.h:31:7:候选函数(隐式复制赋值运算符)不可行:第一个参数没有从'(lambda at MT.cpp:426:17)'到'const sharkLib :: MT'的已知转换
MT.h:31:7:候选函数(隐式移动赋值运算符)不可行:第一个参数没有从'(lambda at MT.cpp:426:17)'到'sharkLib :: MT'的已知转换
我实际上并不重载=
运算符,而是[]
使用每个受支持类型的专用构造函数重载.
.H
protected:
map<string,MT> valueMap;
public:
MT (int value);
MT (std::function<void(Ref*)> ccb);
virtual MT& operator[] (const char* key);
Run Code Online (Sandbox Code Playgroud)
的.cpp
MT::MT (int value)
{
this->type = ValueType::intValue;
this->value.int_ = value;
}
MT::MT (std::function<void(Ref*)> value)
{
this->type = ValueType::ccbValue;
this->value.ccb_ = value;
}
MT& MT::operator[] (const char* key)
{
return this->valueMap[key];
}
Run Code Online (Sandbox Code Playgroud)
用法
MT mt;
mt["int"] = 1;
mt["ccb"] = [](Ref *){ CCLOG("Pressed"); …
Run Code Online (Sandbox Code Playgroud) 想想这个,
struct Person {
std::string name;
Person (const std::string& n) : name(n) {}
std::string getName(int, char) const {return name;} // int, char play no role in this
// simple example, but let's suppose that they are needed.
} *Bob = new Person("Bob"), *Frank = new Person("Frank"), *Mark = new Person("Mark"),
*Tom = new Person("Tom"), *Zack = new Person("Zack");
const std::vector<Person*> people = {Bob, Frank, Mark, Tom, Zack};
Run Code Online (Sandbox Code Playgroud)
因为people
按名称排序,我们可以执行二进制搜索以查找people
具有特定名称的元素.我希望这个看起来像是这样的
Person* person = binarySearch (people, "Tom",
[](Person* p, …
Run Code Online (Sandbox Code Playgroud) 我需要接受lambda函数作为参数并找出它的返回类型.到目前为止,我无法想出任何可行的方法.这是一个例子:
template <typename T1, typename T2>
T1 foo(T2 arg, std::function<T1(T2)> f)
{
return f(arg);
}
...
int n = foo(3, [](int a){ return a + 2; }); <-- ERROR!
Run Code Online (Sandbox Code Playgroud)
怎么做到呢?Boost解决方案也可以.
我有一个当前为不同数据类型重载的函数,并使用lambda(函数指针)初始化这些数据类型.我正在将它们转换为模板实例但尚未成功.
这是重载版本 -
#include <iostream>
using namespace std;
void doSome(int (*func)(int &)){
int a;
a = 5;
int res = func(a);
cout << a << "\n";
}
void doSome(int (*func)(double &)){
double a;
a = 5.2;
int res = func(a);
cout << a << "\n";
}
int main() {
doSome([](int &a){
a += 2;
return 1;
});
doSome([](double &a){
a += 2.5;
return 1;
});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我已经采用了示例int
并且double
为了简化,它们可能是实际代码中的一些完全不同(和复杂)类型.
这是我尝试过的 -
#include <iostream>
using namespace std; …
Run Code Online (Sandbox Code Playgroud) c++ ×9
c++11 ×8
lambda ×7
templates ×3
overloading ×2
binary ×1
c++14 ×1
currying ×1
definition ×1
function ×1
polymorphism ×1
terminology ×1
variadic ×1