2013-03-02 20 views
7

std::function<>の代わりにC++ 11を使用できない場合は、どのような構造を代用する必要がありますか?
代わりに、以下の例のようにあるクラスのプライベートメンバー関数にアクセスすることを基本的に許可する必要があります(std :: functionの他の機能は使用されません)。クラスFooは固定されており、多く変更することはできません。クラスBarにしかアクセスできません。C++ 11より前にstd :: functionと似たものがありますか?

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

このコードはコンパイルべきではない、場合でも明白:ここでは、そのようなクラステンプレートは、(これは一例であり、生産コードでは使用しないでください)ゼロから定義することができる方法の可能性、説明の実装があります構文上の誤りは修正されています。 2つの 'Bar'オブジェクトはプライベートメンバ関数へのポインタで構築されますが、このコードがそのメンバにアクセスすることはできません。これは 'std :: function'とは何の関係もありません。アクセスルールを破ることはありません。 –

答えて

10

C++ 11の前に::関数はstdのようなものはありますか?

はい。 Boost.Function(boost::function<>)があります。これは最近C++標準ライブラリの一部となり、std::function<>のリファレンス実装を提供しました。同様に、Boost.Bind(boost::bind<>())が標準に採用され、std::bind<>()になりました。

任意のタイプの呼び出し可能オブジェクトを保持するために、型消去と呼ばれる技法を実装しています。

#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

実際、ブーストの多くの機能は「事前標準」とみなすことができます。 – leemes

+0

これを最初から構築する方法を示す素敵なコードですが、これはC++ 11であることに留意する必要があります。 ;)私はブーストの実装がはるかに複雑であると思います(私は彼らがプリプロセッサライブラリを使っていると思いますか?) – leemes

+0

@leemes:はい、もちろんです。私は実装の原則が何であるかについて多かれ少なかれ洞察を提供したかっただけです。これはC++ 11だけでなく、非常に基本的なものでもあります。 –

関連する問題