C++/C++ 11中的函数组合

Gab*_* L. 19 c++ function-composition c++11

我目前正在编写一些需要大量函数组合的C++ 11中的加密算法.我必须处理两种类型的构图:

  1. 自己编写一个函数可变次数.在数学上,对于某个函数F,F ^ n(x)=(F ^ {n-1} o F)(x)= F ^ {n-1}(F(x)).

  2. 一起组合不同的功能.例如,对于相同类型的一些函数f,g,h,i,j和k,我将具有f(g(h(i(j(k(x)))))).

就我而言,我使用的是F的以下定义:

const std::vector<uint8_t> F(const std::vector<uint8_t> &x);
Run Code Online (Sandbox Code Playgroud)

我想自己组合这个功能n次.我已经以一种简单的递归方式实现了组合,它工作正常:

const std::vector<uint8_t> compose(const uint8_t n, const std::vector<uint8_t> &x)
{
    if(n > 1)
       return compose(n-1, F(x));

    return F(x);
}
Run Code Online (Sandbox Code Playgroud)

对于这种情况,是否有一种更有效的方法来使用c ++ 11实现此组合但不使用BOOST?如果可能的话,使用这个表格会很棒:

answer = compose<4>(F)(x); // Same as 'answer = F^4(x) = F(F(F(F(x))))'
Run Code Online (Sandbox Code Playgroud)

对于第二种情况,我想实现可变数量的函数的组合.对于给定的一组函数F0,F1,...,Fn具有与F相同的定义,是否有一种有效且合适的方法来组合它们,其中n是可变的?我认为可变参数模板在这里很有用,但在这种情况下我不知道如何使用它们.

谢谢你的帮助.

Igo*_*nik 17

沿着这些方向的东西,也许(未经测试):

template <typename F>
class Composer {
  int n_;
  F f_;
public:
  Composer(int n, F f) : n_(n), f_(f) {}

  template <typename T>
  T operator()(T x) const {
    int n = n_;
    while (n--) {
      x = f_(x);
    }
    return x;
  }
};

template <int N, typename F>
Composer<F> compose(F f) {
  return Composer<F>(N, f);
}
Run Code Online (Sandbox Code Playgroud)

编辑:对于第二种情况(这次测试):

#include <iostream>

template <typename F0, typename... F>
class Composer2 {
    F0 f0_;
    Composer2<F...> tail_;
public:
    Composer2(F0 f0, F... f) : f0_(f0), tail_(f...) {}

    template <typename T>
    T operator() (const T& x) const {
        return f0_(tail_(x));
    }
};

template <typename F>
class Composer2<F> {
    F f_;
public:
    Composer2(F f) : f_(f) {}

    template <typename T>
    T operator() (const T& x) const {
        return f_(x);
    }
};

template <typename... F>
Composer2<F...> compose2(F... f) {
    return Composer2<F...>(f...);
}

int f(int x) { return x + 1; }
int g(int x) { return x * 2; }
int h(int x) { return x - 1; }

int main() {
  std::cout << compose2(f, g, h)(42);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)


小智 9

感谢有趣的问题,2013年的Gabriel.这是一个解决方案.它适用于c ++ 14.

#include <functional>
#include <iostream>
using std::function;

// binary function composition for arbitrary types
template <class F, class G>
auto compose(F f, G g){
  return [f,g](auto x){return f(g(x));};
}

// for convienience
template <class F, class G>
auto operator*(F f, G g){
  return compose(f,g);
}

// composition for n arguments
template <class F, typename... Fs>
auto compose(F f, Fs&&... fs) {
  return f * compose(fs...);
}

// composition for n copies of f
template <int i, class F>
//must wrap chain in a struct to allow partial template specialization
struct multi { static F chain(F f){
    return f * multi<i-1,F>::chain(f);
}};
template <class F>
struct multi <2,F> { static F chain(F f){
    return f * f;
}};
template <int i, class F>
F compose(F f) {return multi<i,F>::chain(f); }

int main(int argc, char const *argv[]) {

  function<double(int)> f = [](auto i){return i + 3;};
  function<int(double)> g = [](auto i){return i * 2;};
  function<int(int)   > h = [](auto i){return i + 1;};

  std::cout
    << '\n' <<  "9 == " << compose(f,g,f)   (0)  \
    << '\n' <<  "9 == " << (f * g * h)      (0)  \
    << '\n' <<  "3 == " << compose<100>(h)  (0)  \
    << '\n';

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

你可以定义

Matrix compose(Matrix f, Matrix g);
Run Code Online (Sandbox Code Playgroud)

要么

Rotation compose(Rotation f, Rotation g);
Run Code Online (Sandbox Code Playgroud)

为各种事情重用这个代码.