1

これは私の最終試験で出題された質問の1つでした。何をすべきかわからない。BindSecArgには()演算子が必要ですが、何が入っているのかわかりません。

この質問では、std::bind2ndに似たものを実装する必要があります。簡単にするために、mainは「for」ループを使用して記述されていますが、「foreach」およびSTLコンテナーで書き換えることができます。

class Functor1 {
  public:
     int operator()(const int & i, const int & j) const {
      return i+j;
     }
};

class Functor2 {
   public:
    int operator()(const int & i, const int & j) const {
       return i*j;
     }
};

template <typename T>
class BindSecArg

};

int main () {
  Functor1 f1;
  for (int i=0; i<10; ++i) std::cout << f1(i,i) << " "; //0 2 4 6 8 10
  std::cout << std::endl;

  Functor2 f2;
  for (int i=0; i<10; ++i) std::cout << f2(i,i) << " "; //0 1 4 9 16 25
  std::cout << std::endl;

  BindSecArg<Functor1> b1(4); //bind second argument of Functor1 to 4
  for (int i=0; i<10; ++i) std::cout << b1(i) << " "; //4 5 6 7 8 9
  std::cout << std::endl;

  BindSecArg<Functor2> b2(4); //bind second argument of Functor2 to 4
  for (int i=0; i<10; ++i) std::cout << b2(i) << " "; //0 4 8 12 16 20
  std::cout << std::endl;
  }

追加のクレジットの質問:あなたの実装はおそらくうまくいきません(これはOKです!)

 class Functor3 {
    public:
      std::string operator()(const std::string & i, const std::string & j) const {
        return i+j;
      }
 };

STLはこの問題をどのように解決しますか?

4

3 に答える 3

3

operator()forはBindSecArg(明らかに)1つの引数を取る必要があり、それが行うことになっているのはoperator()、「バインドされた」ファンクターから呼び出して、(a)渡された「最初の」引数と(b)「バインドされた」2番目の引数を渡すことです。 。

したがって、バインドされたファンクターのクラスのインスタンスを構築する必要があり(その呼び出しを行うことができるように)、2番目の引数を覚えておく必要があります。これらの両方をデータメンバーで処理します。

それは次のようになります:

template <typename T>
class BindSecArg
    T toCall;
    int second;
    public:
    // To initialize, we default-construct the bound-functor-instance, and copy the
    // constructor parameter for our bound-parameter.
    BindSecArg(int second): toCall(), second(second) {}
    // To call, see the above discussion.
    int operator() (int first) { return toCall(first, second); }
};

標準ライブラリ(「STL」とは言わないでください)bind2ndは、Tが「AdaptableBinaryFunction」であることを期待することでこれに対処します。つまりtypedef、のパラメータと結果タイプを識別するメンバーを提供operator()し、これらを使用してこれらを使用して基本クラスから継承します。 typedefをテンプレート型として使用し、基本クラスによって提供されるtypedefを使用して独自のoperator()実装をテンプレート化します。これらは「テンプレートメタプログラミング」の基本的なテクニックの一部であり、すぐに複雑になります。これについては、いくつかの個別の読書リソースを調べる必要があります。

于 2011-07-23T10:47:05.683 に答える
2

おそらくより良い実装があります:

template <typename T>
class BindSecArg
{
public:
   BindSecArg(int value2) : m_value2(value2){ };
   int operator()(int value1) { return T()(value1, m_value2);}
private:
   int m_value2;
};

私があなたの質問へのコメントに投稿したリンクにあなたはstlコードを見つけることができます。

于 2011-07-23T10:39:54.170 に答える
0

内部では、Functor.operator()が呼び出さBindSecArgれ、コンストラクターで指定された値が2番目の引数として渡されます。

于 2011-07-23T10:37:29.210 に答える