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")); 
} 
相關問題