C ++ bind2nd вопрос - PullRequest
       35

C ++ bind2nd вопрос

1 голос
/ 23 июля 2011

Это был один из вопросов, обнаруженных на моем итоговом экзамене.Я не могу понять, что я должен делать.Я знаю, что BindSecArg требует оператор (), но не уверен, что происходит внутри.

В этом вопросе вы должны реализовать нечто подобное std :: bind2nd.Для простоты main пишется с использованием цикла for, но может быть переписан с использованием контейнеров «для каждого» и 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;
  }

Дополнительный кредитный вопрос: ваша реализация, скорее всего, не работает (чтовсе в порядке!) с

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

как STL решает эту проблему?

Ответы [ 3 ]

3 голосов
/ 23 июля 2011

operator() для BindSecArg должен принимать один аргумент (очевидно), и он должен вызывать operator() из "ограниченного" функтора, передавая ему (а) переданный "первым""аргумент и (б) второй" связанный "аргумент.

Итак, нам нужно создать экземпляр класса связанного функтора (чтобы мы могли сделать этот вызов), и нам нужно запомнить второй аргумент.Мы позаботимся об этом обоим с членами данных.

Это выглядит так:

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(), а затем используя их для наследования от базового класса, используя эти typedefs в качестве типов шаблонов, а затем используя typedefsпредоставляется базовым классом для шаблона собственной реализации operator().Это некоторые из основных методов «шаблонного метапрограммирования», и они быстро усложняются.Для этого вам следует поискать несколько отдельных ресурсов для чтения.

2 голосов
/ 23 июля 2011

, вероятно, есть лучшие реализации:

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.

0 голосов
/ 23 июля 2011

Внутри идет вызов Functor.operator (), передавая значение, данное BindSecArg в его конструкторе в качестве второго аргумента.

...