9

これは頻繁に尋ねられて答えられるべきもののように思えますが、私の検索法は失敗しました。

ある種の汎用呼び出し可能オブジェクト (裸の関数、手巻きのファンクター オブジェクト、bind、またはを含む) を受け入れstd::function、アルゴリズムの深さ (つまり、ラムダ) 内でそれを呼び出したい関数を作成しています。

関数は現在、次のように宣言されています。

template<typename T, typename F>
size_t do_something(const T& a, const F& f)
{
   T internal_value(a);
   // do some complicated things
   // loop {
   //   loop {
       f(static_cast<const T&>(internal_value), other_stuff);
       // do some more things
   //   }
   // }
   return 42;
}

関数へのエントリでファンクターがコピーされないことを保証したいので、参照によってファンクターを受け入れます。したがって、オブジェクトの同じインスタンスが実際に呼び出されます。これは、一時オブジェクトを受け入れる唯一の方法であるため、これは const 参照です (これは、手巻きファンクターまたは を使用する場合に一般的ですbind)。

ただし、これにはファンクターoperator()が const として実装する必要があります。私はそれを要求したくありません。どちらも受け入れられるようにしたいです。

両方のケースをカバーするために、このメソッドの 2 つのコピーを宣言できます。1 つは const として受け入れ、もう 1 つは非 const として受け入れます。しかし、コメントには複製したくないコードがかなり隠されているため、そうしたくありません (いくつかのループ構造を含むため、問題を移動するだけでそれらを二次メソッドに抽出することはできません)。 .

また、呼び出す前にファンクターを非 const にする可能性があることも知ってconst_castいますが、これは潜在的に危険だと感じています (特に、ファンクターが const 呼び出し演算子と非 const 呼び出し演算子の両方を意図的に実装している場合は、間違ったメソッドを呼び出す可能性があります)。

std::functionファンクターを/として受け入れることを検討しましたboost::functionが、これは単純な問題であるべき問題に対する重い解決策のように感じます。(特に、ファンクタが何もしないことになっている場合。)

アルゴリズムを複製する以外に、これらの要件を満たす「正しい」方法はありますか?

[注: C++11 を必要としないソリューションを希望しますが、両方の言語のプロジェクトで同様の構成を使用しているため、C++11 の回答にも興味があります。]

4

2 に答える 2