2013-02-25 4 views
6

ich einige Code geschrieben haben, die die Anzahl der Elemente des Vektors zählt eine Funktors und die ref und bind Vorlagen aus boost:: oder std:: (für C unter Verwendung von ++ 11) Namespaces. Ich verwende eine #define, um zwischen boost:: und std:: Namespaces zu wechseln. Ich benutze Boost Version 1.53 und mein Kompilierbefehl ist g++ test.cpp -std=c++11. Ich habe versucht mit GCC-Versionen 4.7.2 und 4.6.3 und ich bekomme die gleichen Fehler mit beiden.keine passende Anruffehler für boost :: ref auftreten, aber nicht mit std :: ref

Ich habe 3 Fragen:

  1. Ich verstehe nicht den Fehler, der 2.
  2. für Beispiel erzeugt wird, ist es möglich, Code wie dieses tragbare durch Umschalten Namensräume nur zu machen?
  3. Gibt es eine gute Referenz, die im Detail die Unterschiede zwischen den std und boost Versionen von bind, ref und function beschreibt? (Ich sah this Frage, aber die Antworten nicht erwähnt ref oder function)

Dank!

P.S. Das Beispiel zeigt nur mein Problem, ich weiß über size() für 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; 
} 

Antwort

4

Beispiel 2 schlägt fehl, da boost::reference_wrapper keine member operator() which forwards the argument(s) haben, im Gegensatz zu std::reference_wrapper. Als solches ist es nur nützlich, um normale Argumente durch Referenz zu übergeben, nicht Funktionen oder Funktoren, von denen erwartet wird, dass sie aufgerufen werden.

Beispiel 3 schlägt fehl, da Boost.Bind relies on a specific protocol to get the result type of the function or functor you pass, wenn Sie die Version ohne expliziten Rückgabetyp verwenden. Wenn Sie eine Zeiger-zu-Funktion- oder Zeiger-zu-Stab-Funktion übergeben, hat das Zurückkehr-Binderobjekt eine verschachtelte , die auf den Rückgabetyp der genannten PTF oder PTMF gesetzt ist. Wenn Sie einen Funktor übergeben, benötigt er einen verschachtelten .
std::bind, auf der anderen Seite, hat einfach keine verschachtelte , wenn Ihr Funktor keine hat.

Beachten Sie, dass Sie können, wie gesagt, ausdrücklich den Ergebnistyp sowohl auf boost::bind und std::bind bieten:

std::for_each(vec.begin(), vec.end(), impl::bind<void>(impl::ref(f3), _1)); 
//            ^^^^^^ 

Welche das Beispiel fixiert und macht es kompilieren.

+0

Der Code, den Sie bereitgestellt haben, funktioniert für mich, ich denke, das ist die einzige Möglichkeit, Boost und Std-Bindungen zu unterstützen. Ich werde cppreference und die Boost-Dokumentation genauer lesen, um die Unterschiede besser zu verstehen. Vielen Dank! – mkm

2

std::ref hat 1 großen Vorteil gegenüber boost::ref: Es bietet eine Varadic perfekt-Weiterleitung operator(), die den Anruf auf seine enthaltene Referenz weiterleiten wird.

boost::ref kann dies praktisch nicht tun, da es eine erhebliche Anzahl von Überlastungen erfordern würde. Um dies zu ermöglichen, bieten boost::bind (und einige andere Klassen) jedoch eine spezielle Handhabung für boost::reference_wrapper.

Verwandte Themen