0

Creating a functor requires an unnecessary boiler plate. The state has to be written 4 times!

struct f{
  double s; // 1st
  f(double state): s(state) {} // 2nd, 3rd and 4th
  double operator() (double x) {
    return x*s;
  }
};

is there a library with a macro that would be just double functor(state)(x){ return x*state; } or something similar.

BOOST_FOREACH is a macro adapter that works well. I'm looking for something similar.

any suggestions on how to write one is appreciated too.

ps. using struct for functor is faster then bind Class's operator() or bind a function as a functor?

Update(1)

in regards to lambdas:

the functor has to be modular, meaning, it should be reusable in other function. lambdas have to be within a function -- lambda has to be in main to be called from main and other functions outside of main, can't call the lambda defined in main.

4

4 回答 4

4

依靠聚合初始化怎么样?简单地不声明构造函数:

struct f {
    double s;
    double operator()(double x) {
        return x * s;
    }
};

像这样使用它

int main()
{       
    auto ff = f{42};
    std::cout << ff(2);
    return 0;
}
于 2013-08-11T20:48:39.130 回答
2

定义你想要的功能,例如,你乘法,作为一个函数,然后std::bind()用来创建一个合适的函数对象:

#include <functional>

double some_operation(double state, double x) {
    return state * x;
}

int main() {
    auto function = std::bind(&some_operation, 17, std::placeholders::_1);
    return function(18);
}

由于通过函数指针的调用通常不能内联,因此您可能希望将函数编写为函数对象:

#include <functional>

struct some_operation {
    double operator()(double state, double x) const {
        return state * x;
    }
};

int main() {
    auto function = std::bind(some_operation(), 17, std::placeholders::_1);
    return function(18);
}

下面是一个测试程序,似乎表明手工函数对象和绑定函数对象的速度大致相同,即我得到的结果是

in 90 ms, functor as a struct; result = 1.5708e+16
in 262 ms, function pointer through bind; result = 1.5708e+16
in 261 ms, function through bind; result = 1.5708e+16
in 87 ms, function object through bind; result = 1.5708e+16
in 88 ms, non-called bind with function; result = 1.5708e+16
in 88 ms, non-called bind with function pointer; result = 1.5708e+16

在使用选项优化的 MacOS 系统上使用最新版本的clang(更准确地说:)。使用和gcc(更准确地说:)给出了类似的结果。clang version 3.4 (trunk 182411)-O2gcc version 4.9.0 20130811 (experimental) (GCC)

函数对象是在本地上下文中构建还是通过模板参数传递给单独的函数似乎有所不同。这种差异很有趣,因为我预计函数的大多数使用bind()都会导致在某处传递生成的函数对象。

该代码基于https://stackoverflow.com/a/18175033/1120273

#include <iostream>
#include <functional>
#include <chrono>

using namespace std;
using namespace std::placeholders;
using namespace std::chrono;

struct fs {
    double s;
    fs(double state) : s(state) {}
    double operator()(double x) {
        return x*s;
    }
};

struct ff {
    double operator()(double x, double state) const {
        return x * state;
    }
};

double fb(double x, double state) {
    return x*state;
}

template <typename Function>
void measure(char const* what, Function function)
{
    const auto stp1 = high_resolution_clock::now();
    double sresult(0.0);
    for(double x=0.0; x< 1.0e8; ++x) {
        sresult += function(x);
    }
    const auto stp2 = high_resolution_clock::now();
    const auto sd = duration_cast<milliseconds>(stp2 - stp1);  
    cout << "in " << sd.count() << " ms, "; 
    cout << what << "; result = " << sresult << endl;
}


int main() {
  double state=3.1415926;

  measure("functor as a struct", fs(state));
  measure("function through bind", std::bind(&fb, _1, state));
  measure("function object through bind", std::bind(ff(), _1, state));


  {
      const auto stp1 = high_resolution_clock::now();
      double sresult(0.0);
      auto function = std::bind(fb, _1, state);
      for(double x=0.0; x< 1.0e8; ++x) {
          sresult += function(x);
      }
      const auto stp2 = high_resolution_clock::now();
      const auto sd = duration_cast<milliseconds>(stp2 - stp1);  
      cout << "in " << sd.count() << " ms, "; 
      cout << "embedded bind with function; result = " << sresult << endl;
  }
  {
      const auto stp1 = high_resolution_clock::now();
      double sresult(0.0);
      auto function = std::bind(&fb, _1, state);
      for(double x=0.0; x< 1.0e8; ++x) {
          sresult += function(x);
      }
      const auto stp2 = high_resolution_clock::now();
      const auto sd = duration_cast<milliseconds>(stp2 - stp1);  
      cout << "in " << sd.count() << " ms, "; 
      cout << "embedded bind with function pointer; result = " << sresult << endl;
  }    

  return 0;
}
于 2013-08-11T19:02:49.593 回答
0

看看BOOST_LOCAL_FUNCTION这似乎正是您正在寻找的,因为您甚至提到了一个宏:)

double s = 42;
double BOOST_LOCAL_FUNCTION(bind& s, double x) {
  return x*s;
} BOOST_LOCAL_FUNCTION_NAME(f)

个人说明:如果您有现代编译器,请使用 C++11 lambda。

于 2013-08-11T21:47:08.753 回答
0

我们为此准备了 lambda:

double s = 42;
auto f = [s](double x) {
    return s * x;  
};

在第 2 行只提到状态(因为您似乎没有在实际表达式中计算一个)。第 1 行的初始化是否算作提及是有争议的,您想要的形式不包含任何必需的初始化,所以我认为这是可以接受的。

在 c++14 中,我们将获得 lambda 捕获语法的扩展,从而允许更简洁的形式:

auto f = [s{42}](double x) {
    return s * x;  
};
于 2013-08-11T20:06:38.720 回答