4

我想创建一个std :: vector对象(或任何其他标准或自定义容器类型)与自定义和任意函数的元素签名都是相同的。如何在不明确定义函数的情况下创建函数的std :: vector?

应该是这样的:

// Define the functions and push them into a vector 
std::vector<????> MyFunctions; 
MyFunctions.push_back(double(int n, float f){ return (double) f/(double) n; }); 
MyFunctions.push_back(double(int n, float f){ return (double) sqrt((double) f)/(double) n; }); 
// ... 
MyFunctions.push_back(double(int n, float f){ return (double) (f * f)/(double) (n + 1); }); 

// Create an argument list 
std::vector<std::pair<int, float>> ArgumentList; 
// ... 

// Evaluate the functions with the given arguments 
// Suppose that it is guarantied that ArgumentList and MyFunctions are in the same size 
std::vector<double> Results; 
for (size_t i=0; i<MyFunctions.size(); i++) 
{ 
    Results.push_back(MyFunctions.at(i)(ArgumentList.at(i).first, ArgumentList.at(i).second)); 
} 

如果可能的话,我不想定义如下明确这些设定的功能:

class MyClass 
{ 
    public: 
     void LoadFunctions() 
     { 
      std::vector<????> MyFunctions; 
      MyFunctions.push_back(MyFoo_00); 
      MyFunctions.push_back(MyFoo_01); 
      MyFunctions.push_back(MyFoo_02); 
      // ... 
      MyFunctions.push_back(MyFoo_nn); 
     } 

    private: 
     double MyFoo_00(int n, float f) { /* ... */ } 
     double MyFoo_01(int n, float f) { /* ... */ } 
     double MyFoo_02(int n, float f) { /* ... */ } 
     // ... 
     double MyFoo_nn(int n, float f) { /* ... */ } 
}; 

一些标准的实现库工具(如使用std::function)是可以的。但是,这样做(如使用升压QT或任何其他文库或框架)的非标准的方式不是优选的。

回答

3

假设你的编译器非常现代的,你可以使用新的std::function型和匿名(拉姆达)函数在C++ 11介绍:

std::vector<std::function<double(int, float)>> MyFunctions; 
MyFunctions.push_back([](int n, float f) { 
    return (double) f/(double) n; 
}); 
MyFunctions.push_back([](int n, float f) { 
    return (double) sqrt((double) f)/(double) n; 
}); 
// ... 
MyFunctions.push_back([](int n, float f) { 
    return (double) (f * f)/(double) (n + 1); 
}); 
+3

你甚至不需要在这里使用'function'(除非你使用VC2010)。无捕获的lambda优雅地降级到函数指针。然而,如果你想使用除函数指针以外的东西,总是使用'function'。 – 2011-12-27 19:15:26

6

这听起来像你想lambda functions。如果你的C++编译器实现了C++ 11标准的这部分,你可以直接使用它们。否则,您可能可以使用Boost PhoenixBoost Lambda

+0

Boost.Lambda已正式废弃了,因为[Boost.Phoenix(http://www.boost.org/libs/phoenix/)V3在升压1.47释放。请推荐Phoenix使用新代码而不是Lambda。 – ildjarn 2011-12-27 19:40:30

+0

@ildjarn:啊,我不知道。谢谢。 – 2011-12-27 22:07:28

2

你可以做到这一点使用std::function和lambda表达式:

#include <vector> 
#include <functional> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 

struct dispatcher { 
    template <typename F, typename Pair> 
    double operator()(const F& func, const Pair& p) const { 
    return func(p.first, p.second); 
    } 
}; 

int main() { 
    std::vector<std::function<double(int,double)>> functions; 
    functions.push_back([](int n, float f) { return double(f)/double(n); }); 

    std::vector<std::pair<int, float>> args = {std::make_pair(1, 10.0f)}; 

    std::vector<double> results; 

    std::transform(functions.begin(), functions.end(), args.begin(), std::back_inserter(results), dispatcher()); 

    std::copy(results.begin(), results.end(), std::ostream_iterator<double>(std::cout, "\n")); 
} 
相关问题