タイプが呼び出し機構にアクセス可能な場所に格納されていない場合、呼び出しサイトで未知のタイプの関数オブジェクトを呼び出すことはできません。
2つのオプションがあります。
C ++ 11またはブーストを使用できる場合は、std::function
respを使用できます。boost::function
:
class A
{
public:
// ...
void doSomeJob(int x)
{
functor(x);
}
private:
std::function<void(int)> functor; // or boost::function when using boost
};
ここで、タイプはfunction
テンプレートのメカニズム内に(暗黙の形式で)格納されます。
それ以外の場合、渡されるすべての関数オブジェクトが特定の基本クラスから派生したクラスタイプを持つことを要求できる場合は、抽象基本クラスを作成できます。
struct AbstractFunctor
{
virtual void operator()(int) = 0;
};
class A
{
public:
// ...
void doSomeJob(int x)
{
(*functor)(x);
}
private:
AbstractFunctor* functor; // or boost::function when using boost
};
ここで、タイプは関数オブジェクトの仮想テーブルに格納されます。
本当にブーストを使用できない場合は、同様のソリューションを自分で作成することもできます。キーワードは「型消去」であり、基本的には、オブジェクトの型を認識して呼び出すことができる既知の基本クラス(私の2番目のソリューションのように)から派生オブジェクトをその場で生成することによって機能します。大まかに次のように実行される可能性があります(テストされていないコード)。
class int_function
{
private:
struct abstract_forward
{
virtual void call(int) = 0;
virtual abstract_forward clone() const = 0;
virtual ~abstract_forward() {}
};
template<typename Functor> struct forward: abstract_forward
{
forward(Functor f): func(f) {}
void call(int i) { func(i); }
abstract_forward clone() const { return new forward<Functor>(func); }
Functor func;
};
public:
template<typename Functor> int_function(Functor f)
{
forwarder = new forward<Functor>(f);
}
int_function(int_function const& other)
{
forwarder = other.forwarder->clone();
}
int_function& operator=(int_function const& other)
{
abstract_forward* newfwd = other.forwarder->clone();
delete forwarder;
forwarder = newfwd;
}
~int_function()
{
delete forwarder}
}
void operator()(int i)
{
forwarder->call(i);
}
private:
abstract_forward* forwarder;
};
class A
{
public:
void doSomeJob(int x)
{
functor(x);
}
private:
int_function functor;
};