2016-06-12 6 views
0

注:私は元の投稿を変更して、最小限の検証可能な例を作成しました。クラスメソッドをC++ 11/14のパラメータとして渡す方法は?

これまでに回答されている場合は申し訳ありませんが、見つかりませんでした。私は古いポインタから関数Cスタイルに移行しようとしています。

以下、私は、それに渡される関数を計算するクラスSolverNonTemplateを持っています。これは匿名関数functionToEvalのために働きます。私は、functionToEvalが解決されるべき問題(構造体SetSystemによって簡略化されて表現される)に、より多くの構造を追加し、追加するという異なるクラスのインスタンス化から渡す必要があります。

私はコンパイルエラーがあるVisual Studioのコミュニティ2015を使用しています:

Error C3867 'SetSystem::DumbSystem': non-standard syntax; use '&' 
to create a pointer to member main.cpp 55. 

コード:すべての

#include "stdafx.h" 
#include <iostream> 
#include <vector> 

class SolverNonTemplate { 
public: 
    template<typename Lambda> 
    void evaluateFunction(const std::vector<double>& varsToSolveValues, 
          Lambda&& functionToEval, 
          std::vector<double>& functionValsOut) 
    { 
     for (int ifunc = 0; ifunc < varsToSolveValues.size(); ++ifunc) 
     { 
      functionValsOut[ifunc] = std::forward<Lambda>(functionToEval)(varsToSolveValues, ifunc); 
     } 
    } 

}; 

double DumbSystem(const std::vector<double>& varsToSolveValues, int indexToReturn) 
{ 
    if (indexToReturn == 0) { 
     return varsToSolveValues[0] * varsToSolveValues[0] - varsToSolveValues[1] * varsToSolveValues[1]; //x^2 - y^2 
    } 
    else { 
     return varsToSolveValues[0] * varsToSolveValues[0] * varsToSolveValues[0] - varsToSolveValues[0] + varsToSolveValues[1]; //x^3 - x*y 
    } 
} 

struct SetSystem 
{ 
    double DumbSystem(const std::vector<double>& varsToSolveValues, int indexToReturn) 
    { 
     if (indexToReturn == 0) { 
      return varsToSolveValues[0] * varsToSolveValues[0] - varsToSolveValues[1] * varsToSolveValues[1]; //x^2 - y^2 
     } 
     else { 
      return varsToSolveValues[0] * varsToSolveValues[0] * varsToSolveValues[0] - varsToSolveValues[0] + varsToSolveValues[1]; //x^3 - x*y 
     } 
    } 
}; 

int main() 
{ 
    std::vector<double> x0Guess = { -30.0, 11.5 }; 
    std::vector<double> fValuesOut; 
    fValuesOut.resize(2); 
    SolverNonTemplate solver; 
    solver.evaluateFunction(x0Guess, DumbSystem, fValuesOut); 
    std::cout << " using anonymous functions.." << std::endl; 
    std::cout << "dumbSystem f[0] = " << fValuesOut[0] << std::endl; 
    std::cout << "dumbSystem f[1] = " << fValuesOut[1] << std::endl; 

    std::cout << "now trying to use function from struct/class /n"; 
    SetSystem system; 
    SolverNonTemplate solver2; 
    solver2.evaluateFunction(x0Guess, system.DumbSystem, fValuesOut); 
    return 0; 
} 
+0

何かを何度も転送してはなりません。フォワーディングは、概念的には動くようなものです。 –

+0

どういう意味ですか? functionToEvalをプレーン関数として使用します。 "別のクラスのメンバである関数"は、メソッドを呼び出すオブジェクトがある場合にのみ意味があります。 – odelande

+0

[mcve]を指定してください。コンパイラエラーが含まれています。あなたがしていることは完全にはわかりません。 – Barry

答えて

0

まず、無料またはその両方のために(関数のアドレスを取るため&を使用メンバー)、それはあなたの意図をより明確にします。

次に、すべての関数(属性値など(1)を参照)を渡すためにsystem.DumbSystemを使用することはできません。関数はクラスにバインドされ、thisは、すべての関数メンバーの暗黙の最初の引数です。あなたがオブジェクトと関数を渡す必要があり、それはあなたも同じ効果を達成するためにラムダを使用することができstd::bind

#include <functional> 
//.... 
using std::placeholders::_1; 
using std::placeholders::_2; 
solver2.evaluateFunction(x0Guess, std::bind(&SetSystem::DumbSystem,std::ref(system),_1,_2), fValuesOut); 

で行われます。

最後に、std::forwardevaluateFunctionは役に立たないと私は確信しています(しかし、私はそれは有害だとは思わない)。引数を別の関数に転送すると、rvalue-ness/lvalue-nessを保持します。ここであなたは誰にも転送していません。


1:これは、クロージャを作成するためのエレガントな方法です。

+0

ありがとうございます!それは魅力のように働く。 –

0

関数のアドレス、つまりsolver.evaluateFunction(x0Guess, &DumbSystem, fValuesOut);を取得する必要があります。 Btw、オーバーヘッドを受け入れることができるのであれば、単純なテンプレートの代わりにstd::function<...>を検討することをお勧めします。

関連する問題