【问题标题】:How to easily apply a function to a collection in C++如何轻松地将函数应用于 C++ 中的集合
【发布时间】:2009-02-26 02:54:51
【问题描述】:

我将图像存储为数组,根据元素的类型进行模板化,例如Image<unsigned>Image<float> 等。我经常需要对这些图像执行操作;例如,我可能需要添加两个图像,或者将图像平方(按元素),等等。所有的操作都是元素级的。我想尽可能地写出类似的东西:

float Add(float a, float b) { return a+b; }
Image<float> result = Add(img1, img2);

甚至更好,比如

complex ComplexCombine(float a, float b) { return complex(a, b); }
Image<complex> result = ComplexCombine(img1, img2);

struct FindMax {
    unsigned currentMax;
    FindMax(): currentMax(0) {}
    void operator(unsigned a) { if(a > currentMax) currentMax = a; }
};

FindMax findMax;
findMax(img);
findMax.currentMax;  // now contains the maximum value of 'img'

现在,我显然不能完全做到这一点;我写了一些东西可以打电话:

Image<float> result = Apply(img1, img2, Add);

但我似乎无法找到一种通用的方法来检测传递的函数/函数对象的返回类型,所以我上面的ComplexCombine 示例已失效;另外,我必须为我想传递的每个参数写一个新的(这似乎是不可避免的)。

对如何实现这一点有任何想法(尽可能少的样板代码)?

【问题讨论】:

    标签: c++ templates mapreduce


    【解决方案1】:

    这就是为什么他的 STL 中的 unary_function、binary_function 等类型具有 result_type 类型定义的原因。如果你使用 std::ptr_fun,你可以通过 Apply 来利用它,

    例如

    template<typename Func, typename Arg, typename Result = Func::result_type>
    Image<Result> Apply(Arg a1, Arg a2, Func f) {
            return Image<Result>(f(a1,a2));
    }
    

    然后做,

    Apply(img1, img2, std::ptr_fun(&Add));
    

    好的,你抓住了我,我没有测试它。还是可以的,但是不能直接使用一些 STL 功能需要做更多的工作

    #include <iostream>
    
    template<typename T>
    struct Image {
      T val_;
      Image(const T& val) : val_(val) {}
    };
    
    template<typename Arg1, typename Arg2, typename Result>
    struct image_fun_adapter {
      Result (*f)(Arg1, Arg2);
      Image<Result> operator()(const Image<Arg1>& a1, const Image<Arg2>& a2) {
        return Image<Result>(f(a1.val_, a2.val_));
      }
    };
    
    template<typename Arg1, typename Arg2, typename Result>
    image_fun_adapter<Arg1,Arg2,Result> image_fun_ptr(Result (*f)(Arg1,Arg2)) {
      image_fun_adapter<Arg1,Arg2,Result> rv;
      rv.f = f;
      return rv;
    }
    
    float Add(float a, float b) { return a + b; }
    
    int main() {
      Image<float> a(1.0);
      Image<float> b(12.5);
      // this is the cute bit:
      Image<float> c = image_fun_ptr(&Add)(a,b);
    
      std::cout << c.val_ << std::endl;
      return 0;
    }
    

    【讨论】:

    • 我得到 (1) 错误:预期的类型说明符 (1) 错误:预期的 '>' (2) 错误:默认模板参数可能不会在函数模板中使用(我已经对这些行进行了编号根据您的示例。)我正在使用 gcc v4.2.4。
    【解决方案2】:

    模板专业化!

    template<typename T>
    T Add(const T &left, const T &right)
    {
        return left + right;
    }
    
    template<typename T>
    struct AddTwo
    {
        T operator()(const T &left, const T &right)
        {
            return Add(left, right);
        }
    };
    
    // something like this (not exactly sure)
    template<std::vector<typename V>>
    std::vector<V> Add(const std::vector<V> &left, const std::vector<V> &right)
    {
        assert(left.size() == right.size());
    
        std::vector ret(left.size());
    
        std::transform(left.const_begin(), left.const_end(), right.const_begin(), ret.begin(), AddTwo());
    
        return ret;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-06-10
      • 1970-01-01
      • 2011-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-01
      相关资源
      最近更新 更多