2015-02-19 15 views
5

Aşağıda, bir nesneyi, üye işlevini ve argümanlarını kabul eden ProxyCall adlı bir şablon işlevim var. Sadece üye işlevine çağrı yönlendirir.Şablonlu işlevlerde const başvurularının türden çıkarılması

Şablon niteleyicileri kullanmadan işlevi çağırabilir (çok sayıda argümanla bu tür çağrılarda ton olduğunu düşünün). Tür dökümü çoğunlukla çalışır ancak const başvuru parametrelerini örnekte olduğu gibi iletmeye çalıştığımda derleyiciler (hem msvc ve gcc 4.9) barf çalışır.

#include <string> 

struct Widget { 
    void f(const std::string& s, bool b) {} 
}; 


template<typename T, typename... Args> 
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) { 
    (obj.*method)(std::forward<Args>(args)...); 
} 


int main(int argc, char* argv[]) 
{ 
    Widget w; 
    std::string s; 

    ProxyCall<Widget, const std::string&, bool>(w, &Widget::f, s, true); // OK 
    ProxyCall(w, &Widget::f, (const std::string&)s, true); // also OK 

    ProxyCall(w, &Widget::f, s, true); // ERROR: template parameter is ambiguous 
    return 0; 
} 

Sorum şu: derleyici otomatik olarak açık şablon elemeleri veya açık döküm başvurmadan türlerini anlamak böylece yukarıdaki kodunu değiştirmek nasıl. Derleyicinin, Widget :: f.

+1

'şablon void ProxyCall (T & obj, M yöntemi, Args && ... args) ' – zch

+1

veya alternatif olarak 'template void ProxyCall (T & obj, void (T: : * yöntem) (Margs ...), Args && ... args) – zch

cevap

3
template<typename T, typename... Args> 
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) { 
    (obj.*method)(std::forward<Args>(args)...); 
} 

Args ikinci bağımsız değişken ve ProxyCall üzere arkadan bağımsız değişkenleri her iki çıkarılır.
Üçüncü durumda, s, const değil, Args, [std::string&, bool] sonucuna çıkarılır (başvuruları daraltma ve yönlendirme başvuruları için kuralları çağırın). Bununla birlikte, üye işlevleri imzası açıkça farklıdır. Böylece ilk tip için Args'da iki farklı tür çıkarılır, bu da kesinti kesintisine yol açar.

Bunun yerine, parametre tipleri ve bağımsız değişkenler, her iki bağımsız hale - ve ref-eleme uğruna, nesne bağımsız değişken ileri:

template<typename T, typename F, typename... Args> 
void ProxyCall(T&& obj, F method, Args&&... args) { 
    (std::forward<T>(obj).*method)(std::forward<Args>(args)...); 
}