2013-02-18 26 views
57

, biz bir lambda fonksiyonu sarmak veya saklayabilir nasıl çalışır std :: Bir std::function:fonksiyon Biliyorsun

#include <iostream> 
#include <functional> 
int main() 
{ 
    std::function<float (float, float)> add = [](float a, float b) 
    //   ^^^^^^^^^^^^^^^^^^^^ 
    { 
     return a + b; 
    }; 

    std::cout << add(1, 2) << std::endl; 
} 

sorum bunun bir şablon sınıftır görebilirsiniz ama kabul edebileceği gibi etrafında std::function olduğunu işlev her türlü işlev imzası. Bu formda return_value (first_arg, second_arg) örneğin float (float, float) için

.

std::function'un yapısı nedir ve x(y,z) gibi bir işlev imzasını nasıl kabul eder ve nasıl çalışır? C++ 'da float (float, float) yeni geçerli bir ifade var mı?

+7

C++ cinsinden bakma türü silme. –

+5

Her zaman derleyici ' '' başlığını açın (Ben tüm önemli derleyiciler gemi std başlıklarını inanmak C++ kodu gibi) ve inceleyin veya [Boost.Function] (http://www.boost.org/doc bir göz olabilir /libs/1_53_0/doc/html/function.html). – Angew

+4

@Angew: Evet, çok eğitici, +1. Bence std :: function, C++ dilinin hemen her yönüne değiniyor ... –

cevap

93

Bazı type erasure technique kullanır.

Bir olasılık şablonları ile karışık alt tipi polimorfizm kullanmaktır.

template <typename T> 
struct function; 

template <typename Result, typename... Args> 
struct function<Result(Args...)> { 
private: 
    // this is the bit that will erase the actual type 
    struct concept { 
     virtual Result operator()(Args...) const = 0; 
    }; 

    // this template provides us derived classes from `concept` 
    // that can store and invoke op() for any type 
    template <typename T> 
    struct model : concept { 
     template <typename U> 
     model(U&& u) : t(std::forward<U>(u)) {} 

     Result operator()(Args... a) const override { 
      t(std::forward<Args>(a)...); 
     } 

     T t; 
    }; 

    // this is the actual storage 
    // note how the `model<?>` type is not used here  
    std::unique_ptr<concept> fn; 

public: 
    // construct a `model<T>`, but store it as a pointer to `concept` 
    // this is where the erasure "happens" 
    template <typename T, 
     typename=typename std::enable_if< 
      std::is_convertible< 
       decltype(t(std::declval<Args>()...)), 
       Result 
      >::value 
     >::type> 
    function(T&& t) 
    : fn(new model<typename std::decay<T>::type>(std::forward<T>(t))) {} 

    // do the virtual call  
    Result operator()(Args... args) const { 
     return (*fn)(std::forward<Args>(args)...); 
    } 
}; 

(Ben basitlik uğruna bazı şeyleri gözardı unutmayın: Burada basitleştirilmiş bir versiyonudur sadece genel yapısı hakkında bir fikir vermek için, var belki başka sorunlar da kopyalanamaz ve; bu kullanmayın gerçek kodda)

+6

+1. Bu cevap için daha fazla zaman ayıramam çok üzücü. – xmllmx

+0

@Martinho, 'Niteliksiz' tanımı nerede? – xmllmx

+2

@xmllmx Bu, tüm niteleyicileri (const, volatile, &, ve &) bir türden kaldıran bir diğer ad şablonu. Burada 'Bare' aynı: http://flamingdangerzone.com/cxx11/2012/05/29/type-traits-galore.html#bare_types (O zamandan beri daha iyi bir isim :) –