Как использовать std :: transform с шаблонами - PullRequest
1 голос
/ 27 ноября 2009

Я изо всех сил пытаюсь выяснить, почему я не могу заставить преобразование работать с шаблоном класса.

Вот упрощенная версия шаблона класса:

template<typename T>
class base
{
public :
  base() : all_() {}
  ~base() {}
public:
  bool add(T t)
  {
    typename vector<T>::iterator itr 
      = lower_bound(all_.begin(), all_.end(), t);
    if ( itr == all_.end() || *itr != t )
      {
        all_.push_back(t);
        cout << "ok" << endl;
        return true;
      }
    cout << "failed" << endl;
    return false;
  }
  static bool addTo(base<T> *c, T t)
  {
    return c->add(t);
  }
private :
  vector<T> all_;
};

И здесь я пытаюсь использовать transform для захвата всего вывода bool из функции add member:

main()
{
  base<int> test;
  vector<bool> results;
  vector<int> toAdd;
  toAdd.push_back(10);
  toAdd.push_back(11);
  toAdd.push_back(10);
  transform( toAdd.begin(), toAdd.end(),
             back_inserter(results),
             bind1st( (bool(*)(base<int>*,int))base<int>::addTo, &test ) );
}

Цель состоит в том, чтобы вставить каждый элемент контейнера toAdd, используя base :: add или base :: addTo, и захватить результаты bool в векторном результате

Ответы [ 2 ]

6 голосов
/ 27 ноября 2009

Попробуйте:

  transform( toAdd.begin(), toAdd.end(),
         back_inserter(results),
         bind1st( mem_fun(&base<int>::add), &test ) );

Проблема не в шаблоне, а в том, что bind1st полагается на дополнительную поддержку в работе (см. http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html). AFAIK. Он никогда не сможет работать с простыми старыми указателями на функции.

boost::bind может делать больше вещей, если вы хотите внести это. Для этой ситуации вам это не нужно, хотя: mem_fun превращает нестатическую функцию-член в адаптируемую двоичную функцию. addTo поэтому также не требуется, но если вам нужно было использовать статическую функцию-член в аналогичной ситуации, тогда есть ptr_fun.

0 голосов
/ 27 ноября 2009

Добавьте в свой базовый класс следующее:

typedef base<T>* first_argument_type;
typedef T second_argument_type;
typedef bool result_type;

bool operator () (base<T> *c, T t) const {
    return c->add(t);
}

и измените преобразование на:

transform(toAdd.begin(), toAdd.end(),
          back_inserter(results), bind1st(base<int>(), &test ));
...