Я написал некоторый код, который подсчитывает количество элементов вектора с помощью функтора и ref
а также bind
шаблоны из boost::
или же std::
(для C ++ 11) пространства имен. Я использую #define
переключаться между boost::
а также std::
Пространства имен. Я использую версию Boost 1.53, и моя команда компиляции g++ test.cpp -std=c++11
, Я пытался с gcc версий 4.7.2 и 4.6.3, и я получаю одинаковые ошибки с обоими.
У меня есть 3 вопроса:
std
а также boost
версии bind
, ref
а также function
? (Я видел этот вопрос, но ответы не упоминают ref
или же function
)Спасибо!
Постскриптум Пример только иллюстрирует мою проблему, я знаю о size()
за std::vector
🙂
//#define USE_STD
#ifdef USE_STD
#include <functional>
using namespace std::placeholders;
namespace impl = std;
#else
#include <boost/version.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
namespace impl = boost;
#endif
#include <iostream>
#include <algorithm>
#include <vector>
class Item {
int id_;
public:
Item(int id) : id_(id) {};
};
template <typename ITEM>
class Counter {
int count_;
public:
// typedef void result_type; // adding this fixes Example 3 when impl=boost
Counter() : count_(0) {};
void operator()(ITEM* item) {count_++;}
int operator()() {return count_;}
};
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
#ifndef USE_STD
std::cout << "BOOST_LIB_VERSION=" << BOOST_LIB_VERSION << std::endl;
#endif
// allocate
typedef std::vector<Item*> ItemVec;
ItemVec vec;
for (int i = 0; i < 9; ++i) {vec.push_back(new Item(i));}
// Example 1, works for BOTH
Counter<Item> f1;
f1 = std::for_each(vec.begin(), vec.end(), f1);
std::cout << "f1()=" << f1() << std::endl;
// Example 2, works with impl=std ONLY
// COMPILE ERROR with impl=boost: "no match for call to ‘(boost::reference_wrapper<Counter<Item> >) (Item*&)’"Counter<Item> f2;
std::for_each(vec.begin(), vec.end(), impl::ref(f2));
std::cout << "f2()=" << f2() << std::endl;
// Example 3, works with impl=std ONLY
// COMPILE ERROR with impl=boost "no type named ‘result_type’ in ‘class Counter<Item>’"// this can fixed by adding the typedef described above
Counter<Item> f3;
std::for_each(vec.begin(), vec.end(), impl::bind(impl::ref(f3), _1));
std::cout << "f3()=" << f3() << std::endl;
// clean up
for (ItemVec::iterator it = vec.begin(); it != vec.end(); ++it) {
delete *it;
}
vec.clear();
return 0;
}
Пример 2 терпит неудачу, потому что boost::reference_wrapper
не имеет член operator()
который передает аргумент (ы), В отличие от std::reference_wrapper
, Как таковой, он полезен только для передачи нормальных аргументов по ссылке, а не функций или функторов, которые должны вызываться.
Пример 3 терпит неудачу, потому что Boost.Bind полагается на определенный протокол, чтобы получить тип результата функции или функтора, который вы передаете, если вы используете версию без явного типа возвращаемого значения. Если вы передадите ему указатель на функцию или указатель на член-функцию, объект связывателя с возвращаемым значением имеет вложенный result_type
установите тип возврата указанного PTF или PTMF. Если вы передаете функтор, он нуждается во вложенном result_type
,
std::bind
, с другой стороны, просто не имеет вложенных result_type
если у вашего функтора его нет.
Обратите внимание, что, как я уже сказал, вы можете явно указать тип результата для обоих boost::bind
а также std::bind
:
std::for_each(vec.begin(), vec.end(), impl::bind<void>(impl::ref(f3), _1));
// ^^^^^^
Который исправляет пример и компилирует его.
std::ref
имеет 1 главное преимущество перед boost::ref
: Это обеспечивает идеальную отправку operator()
, который перенаправит вызов на содержащуюся ссылку.
boost::ref
практически не может сделать это, так как это потребует значительного количества перегрузок. Чтобы позволить это, однако, boost::bind
(и несколько других классов) все обеспечивают специальную обработку для boost::reference_wrapper
,