2013-10-17 19 views
6

クロージャと組み合わせて使用​​すると、std :: functionのフードの下で何が起きているのか把握しようとしています。私はそれの周りに私の頭をラップすることはできません、例えば:どのコンストラクタが呼び出されている? 誰かが、次の例で必要な機能をサポートするstd :: functionの代わりに、最小限のドロップの実例を投稿できますか?ここでC++クロージャとstd :: function

#include <functional> 

int main(int argc, char* argv[]) 
{ 
    int mybool = 5; 

    auto foo = [&] (int arg) { 
     return mybool * arg; 
    }; 

    std::function<int(int)> foo2 = foo; 

    int result = foo2(42); 

    return 0; 
} 
+2

。それはテンプレートのみのコードなので、簡単に*自分で見ることができます。 –

+1

興味深いことが分かっているなら、['std :: bind'](http://en.cppreference.com/w/cpp/utility/functional/bind)はあなたを積極的に駄目にします。 – WhozCraig

+0

テンプレートに加えて、オープンソース(stdlibC++は通常GCCで使用され、libC++は通常clangで使用される)の大きなC++ライブラリがいくつかあるので、テンプレート化されていないコードも見ることができます。 –

答えて

7

は、最小限の例です:

template <class F> 
struct Decomposer; 

template <class R, class A> 
struct Decomposer<R (A)> 
{ 
    typedef R return_type; 
    typedef A argument_type; 
}; 


template <class F> 
struct my_function 
{ 
    typedef typename Decomposer<F>::return_type return_type; 
    typedef typename Decomposer<F>::argument_type argument_type; 

    return_type operator() (argument_type arg) const { 
    return (*impl)(arg); 
    } 

    template <class From> 
    my_function(From &&from) 
    { 
    struct ConcreteImpl : Impl 
    { 
     typename std::remove_reference<From>::type functor; 
     ConcreteImpl(From &&functor) : functor(std::forward<From>(functor)) {} 
     virtual return_type operator() (argument_type arg) const override 
     { 
     return functor(arg); 
     } 
    }; 
    impl.reset(new ConcreteImpl(std::forward<From>(from))); 
    } 

private: 
    struct Impl { 
    virtual ~Impl() {} 
    virtual return_type operator() (argument_type arg) const = 0; 
    }; 

    std::unique_ptr<Impl> impl; 
}; 

核となるアイデアは、その型を知らなくても、実際の閉鎖を保存するために型消去を使用することです:仮想Impl::operator()を参照し、ローカルに定義されたタイプ固有ホルダーConcreteImpl。マジック:一言で

Live example

関連する問題