簡體   English   中英

帶模板的高階函數?

[英]Higher-order functions with templates?

我已經用Clojure(一種函數式語言)編程了一段時間了,我必須在類中使用C ++。 我一直在嘗試使用我在Clojure中享受的一些功能(例如,高階函數,lambdas,參數線程,動態類型等)但我已經碰到了一些磚牆。

首先,我實現了一個帶有兩個參數的函數get

  1. 集合(向量,列表,哈希映射等),和
  2. 一個索引

並返回該索引處的元素。

我還實現了一個函數conj ,它有兩個參數:

  1. 集合(矢量,列表,隊列等),和
  2. 元素/對象(集合的任何類型)

並返回添加了元素的集合。 在向量的情況下,這與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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM