[英]Higher-order functions with templates?
我已經用Clojure(一種函數式語言)編程了一段時間了,我必須在類中使用C ++。 我一直在嘗試使用我在Clojure中享受的一些功能(例如,高階函數,lambdas,參數線程,動態類型等)但我已經碰到了一些磚牆。
首先,我實現了一個帶有兩個參數的函數get
:
並返回該索引處的元素。
我還實現了一個函數conj
,它有兩個參數:
並返回添加了元素的集合。 在向量的情況下,這與push_back
大致相同。
現在,我希望能夠使用高階函數“轉發”或“線程化”參數,如下所示:
using std::vector;
vector<double> my_vec;
forward(my_vec, // take "my_vec"
conj(0.1), // "push" the value of 0.1 to the back of "my_vec"
get(0), // retrieve the first value
inc); // increment that value
它與inc(get(conj(my_vec, 0.1), 0);
但是很多(!)更具可讀性。
在這種情況下, forward
的返回值應為1.1。
為了使forward
函數起作用,初始參數之后的參數需要都是高階函數。 也就是說,它們需要類似於以下工作:
template<typename Func>
Func get(int i){
return [i](vector<boost::any> coll)
-> boost::optional<boost::any> {
return get(coll, i);
};
}
但是,編譯器無法推斷要返回的lambda函數的類型。 此外,我的猜測,根據我極其有限的經驗boost::any
,就是它不能給轉換vector<double>
以vector<boost::any>
,盡管明顯要求boost::any
它可以作為幾乎任何類型的替代品。
我希望get
函數是通用的,所以我不想使用boost::function<double (vector <double>, int)>
或任何類似的特定類型。
另外,如果從get
請求的索引超出范圍,我使用boost::optional
而不是vector
來返回null_ptr
。
就目前而言,這是我的forward
函數的外觀:
template <typename T1>
optional<T1> forward (T1 expr1){
return expr1;
}
template <typename T1, typename T2>
optional<T1> forward (T1 expr1, T2 expr2){
return forward(expr2(expr1));
}
template <typename T1, typename T2, typename T3>
optional<T1> forward (T1 expr1, T2 expr2, T3 expr3){
return forward(expr2(expr1), expr3);
}
等......
關於如何使這個forward
功能起作用的任何想法?
我也非常確定有一種更有效的方法來實現它,而不是像我一樣進行arity-overloading。
這就是我能想到的:
http://coliru.stacked-crooked.com/a/039905c5deff8dcf
我使用了三種不同變體的完全成熟的仿函數,而不是lambdas。 它支持您的示例,不需要類型擦除等(例如boost :: any或std :: function)。
boost::optional<double> result = forward(my_vec, conj(0.1), get(0), inc);
此外, forward
功能實現為可變參數模板,允許任意數量的功能。
代碼是未經修改的,但也許它可以提供一些靈感。
編輯: 安東是絕對正確的,我對前鋒的實施是不必要的復雜。 上面的鏈接現在指向他修改后的代碼版本。
只是Horstling的答案的補充,實際上forward
可以更容易實現:
template <typename Value>
Value forward(Value v) {
return v;
}
template <typename Value, typename Func, typename... Funcs>
auto forward(Value v, Func f, Funcs... fs) -> decltype(forward(f(v), fs...)) {
return forward(f(v), fs...);
}
而且C ++ 14使事情變得更加甜美:
template <typename Value>
Value forward(Value v) {
return v;
}
template <typename Value, typename Func, typename... Funcs>
decltype(auto) forward(Value v, Func f, Funcs... fs) {
return forward(f(v), fs...);
}
看看這里的完整代碼(Coliru似乎支持提升)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.