2013-03-02 19 views
7

Jaki konstrukt powinien być użyty jako surogat dla std::function<>, gdy C++ 11 jest niedostępny?
Alternatywa powinna zasadniczo umożliwiać dostęp do prywatnych funkcji składowych jednej klasy z innej klasy, jak w poniższym przykładzie (inne funkcje funkcji std :: nie są używane). Klasa Foo jest stała i nie można jej zmienić zbyt wiele, mam dostęp tylko do paska klasy.Czy istnieje coś podobnego do std :: function before C++ 11?

class Foo { 
    friend class Bar; // added by me, rest of the class is fixed 
    private: 

    void doStuffFooA(int i); 
    void doStuffFooB(int i); 
}; 

class Bar { 
    public: 

    Bar(Foo foo, std::function< void (const Foo&, int) > func) { 
    myFoo = foo; 
    myFooFunc = func; 
    }; 

    private: 

    doStuffBar(const &Foo foo) { 
    myFooFunc(foo, 3); 
    } 

    Foo myFoo; 
    std::function< void (const Foo&, int) > myFooFunc; 
} 

int main() { 

    Foo foo(...); 

    Bar barA(foo, &Foo::doStuffFooA); 

    Bar barB(foo, &Foo::doStuffFooB); 
    ... 
} 
+1

Kod ten nie powinien skompilować, nawet gdy oczywiste błędy składniowe są naprawione. Dwa obiekty "Bar" są konstruowane ze wskaźnikami do prywatnych funkcji składowych, ale kod, w którym to występuje, nie ma dostępu do tych elementów. Nie ma to nic wspólnego z 'std :: function'; nie może złamać reguł dostępu. –

Odpowiedz

10

Czy jest coś podobnego do std :: funkcję przed C++ 11?

Tak. Istnieje funkcja Boost.Function (boost::function<>), która ostatnio stała się częścią Standardowej Biblioteki C++ i dostarczyła implementację referencyjną dla std::function<>; podobnie, Boost.Bind (boost::bind<>()) został przyjęty przez Standard i stał się std::bind<>().

Implementuje technikę o nazwie typu wymazanie do przechowywania obiektów wymienialnych dowolnego typu. Tutaj jest to możliwe, ilustrujące realizacja jak taki szablon klasy można zdefiniować od podstaw (nie używać w kodzie produkcyjnym, jest to tylko przykład):

#include <memory> 

template<typename T> 
struct fxn { }; 

template<typename R, typename... Args> 
struct fxn<R(Args...)> 
{ 

public: 

    template<typename F> 
    fxn(F&& f) 
     : 
     _holder(new holder<typename std::decay<F>::type>(std::forward<F>(f))) 
    { } 

    R operator() (Args&&... args) 
    { _holder->call(std::forward<Args>(args)...); } 

private: 

    struct holder_base 
    { virtual R call(Args&&... args) = 0; }; 

    template<typename F> 
    struct holder : holder_base 
    { 
     holder(F&& f) : _f(std::forward<F>(f)) { } 
     R call(Args&&... args) { return _f(std::forward<Args>(args)...); } 
     F _f; 
    }; 

    std::unique_ptr<holder_base> _holder; 
}; 

#include <iostream> 

int main() 
{ 
    fxn<void()> f = [] { std::cout << "hello"; }; 
    f(); 
} 
+0

Rzeczywiście, wiele funkcji z doładowania może być postrzeganych jako "standardowe standardy". – leemes

+0

Dobry kod, który pokazuje, jak możemy to zbudować od zera, ale trzeba pamiętać, że jest to C++ 11. ;) Wydaje mi się, że implementacja boost jest o wiele bardziej skomplikowana (domyślam się, że używają do tego swojej biblioteki preprocesora?) – leemes

+0

@leemes: Tak, oczywiście. Chciałem tylko zapewnić wgląd w to, czym jest zasada realizacji, mniej więcej. Jest to nie tylko C++ 11, ale także bardzo pierwotne. –

Powiązane problemy