ファイルから読み取ったデータに基づいて関数を呼び出せるようにしたい。そのため、アイテムの種類ごとに、目的のリーダーメソッドを呼び出します。このコードを書きましたが、関数ポインターをマップに追加する場所をコンパイルしません。なにが問題ですか?
#include <vector>
#include <map>
#include <iostream>
class reader
{
std::map< std::string, void(*)()> functionCallMap; // function pointer
void readA(){ std::cout << "reading A\n";};
void readB(){ std::cout << "reading B\n";};;
public:
reader()
{
*functionCallMap["A"] = &reader::readA;*
*functionCallMap["B"] = &reader::readB;*
}
void read()
{
auto (*f) = functionCallMap["A"];
(*f)();
}
};
コンストラクターでマップを埋めています。
std::function
をラムダまたはstd::bind
とともに使用できます。
class reader
{
std::map<std::string, std::function<void()>> functionCallMap;
void readA() { std::cout << "reading A\n"; };
void readB() { std::cout << "reading B\n"; };
public:
reader()
{
functionCallMap["A"] = [this]() { readA(); };
functionCallMap["B"] = std::bind(&reader::readB, this);
}
void read()
{
functionCallMap["A"]();
functionCallMap["B"]();
}
};
次のように、メンバー関数へのポインターを使用する必要があります。
class reader
{
using FuncPtr = void(reader::*)(); // function pointer
std::map< std::string, FuncPtr> functionCallMap;
void readA(){ std::cout << "reading A\n"; }
void readB(){ std::cout << "reading B\n"; }
public:
reader()
{
functionCallMap["A"] = &reader::readA;
functionCallMap["B"] = &reader::readB;
}
void read()
{
auto f = functionCallMap["A"];
(this->*f)();
}
};
int main()
{
reader r;
r.read();
}
これまでのところ、 this と this の2つの答えがあります。
明らかな違いは、1つは_std::function
_を使用し、もう1つは関数ポインターを使用することです。これは重要な違いではありません!!
重要な点は、メンバー関数が非静的メンバー関数であることです。したがって、これらはnotvoid()
型です。
それらはvoid(reader::*)()
型です。したがって、タイプのオブジェクトがリーダーである場合にのみ呼び出すことができます。これは、隠されたパラメーターとしてある程度理解できます。
最初の答え は、correctタイプを指定することで問題を修正するだけです。これは、関数ポインター(提示)を使用して行うことができますまたは_std::function
_を使用します(後者ははるかに高価です!)。
2番目の答え は、binding関数ポインタをクラスの特定のインスタンス。バインド後、タイプは実際にvoid()
になります。未加工の関数ポインタを使用してこれを行うことはできません(オブジェクト/関数のペアではなく関数のみを指すことができるためです!)。
私はこの解決策になりました。それは仕事をしますが、私はその美学についていくつかの疑問を持っています。とにかく、要約すると、私はこのコードで終わった:
#include <map>
#include <iostream>
#include <functional>
class reader
{
std::map< std::string, std::function<void(std::string tableName)>> functionCallMap; // function pointer
void readA(const std::string tableName){ std::cout << "reading:" << tableName<< "\n"; }
void readB(const std::string tableName){ std::cout << "reading:" << tableName <<"\n"; }
public:
reader()
{
functionCallMap["A"] = std::bind(&reader::readA, this, std::placeholders::_1);
functionCallMap["B"] = std::bind(&reader::readA, this, std::placeholders::_1);
}
void read()
{
const std::string table_name = "A";
functionCallMap[table_name](table_name);
}
};
int main()
{
reader r;
r.read();
}
テーブル名をリーダーに渡します。これはbindとplaceholderでうまく行われます。