6

Bu soru,
Passing a member function pointer to an overloaded class method into a template function adresinden üretilmiştir.
Bu soruyu anlamak için bunu okumana gerek yok. Muhtemelen her iki soru da aynı cevaba sahip olacak.Standart kitaplık yöntemleri ile üye işlev işaretçisi sorunu

compiler error for below simple code alıyorum.

#include<set> 
template<typename Return, typename T> 
T ReceiveFuncPtr (Return (T::*Method)(const int&)) 
{ 
    T obj; // Found and declared an object of actual container class 
    (obj.*Method)(1); // Some processing 
    return obj; // Returned that container class object with RVO 
} 
int main() 
{ 
    ReceiveFuncPtr(&std::set<int>::insert); // ERROR 
} 

hata ilginçtir:

In function 'int main()': 
error: no matching function for call to 'ReceiveFuncPtr(<unresolved overloaded function type>)' 
    ReceiveFuncPtr(&std::set<int>::insert); // ERROR 
             ^ 
note: candidate is: 
note: template<class Return, class T> T ReceiveFuncPtr(Return (T::*)(const int&)) 
T ReceiveFuncPtr (Return (T::*Method)(const int&)) 
^ 
note: template argument deduction/substitution failed: 
note: mismatched types 'const int&' and 'std::initializer_list<int>' 
    ReceiveFuncPtr(&std::set<int>::insert); // ERROR 
             ^ 
note: mismatched types 'const int&' and 'std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}' 
note: mismatched types 'const int&' and 'std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}' 
note: mismatched types 'const int&' and 'std::set<int>::value_type&& {aka int&&}' 
note: couldn't deduce template parameter 'Return' 

Eğer not s bakarsak yakından o zaman bu derleyici doğru dışındaki tüm diğer yöntemleri eşleşen olduğunu görünür! Bu durumda derleyici, insert(const std::set<int>::value_type&) aka const int& ile eşleşmelidir. ReceiveFuncPtr()'u başka bir aşırı yüklemeyle eşleştirmek için değiştirirseniz, bu aşırı yükü atlayarak başarısız olur.

Bu durumu hata ayıklamak için, el yapımı std::set sürümünü oluşturdum. Ama compiles fine o:

template<typename T, typename T2 = void> 
struct MySet 
{ 
    std::pair<T,bool> insert (const T& i) { return std::pair<T,bool>(T(),true); } 
    std::pair<T,bool> insert (T&& i) { return std::pair<T,bool>(T(),true); } 
    void insert (std::initializer_list<T> i) { return false; } 
} 
int main() 
{ 
    ReceiveFuncPtr(&MySet<int>::insert); // OK 
} 

sörf sonra bu yazı geldi: Bunlar birbirine olsa
What are the rules for function pointers and member function pointers to Standard functions?

, sorunu çözmez.

Soru: Aynı şey el yazısıyla sınıf yöntemi için geçtiğinde üye işlevi ikame standart kütüphanesi yönteminin durumunda başarısız Neden?

Güncelleme: Doğru cevap baktıktan sonra

, ben insert kullanılamaz eminim. Tek yol bu sorun için bir aşırı sıkıcı olan çirkin typecasting olurdu.
Bir zarif çözümtemplate karışımını ve olmayan template sürümleri ekin aksine sadece template d sürümüne sahip std::set<int>::emplace<const int&> kullanmaktır.
Çağrı aşağıda fonksiyonu: compiles fine Üstü

ReceiveFuncPtr(&std::set<int>::emplace<const int&>); 

.

+0

aslında derler ve görsel stüdyo 2013 ile MSVC üzerinde iyi çalışır: 'şablon T exec (E (T :: * fonk) (#define ve i)) { \t T T; \t (t. * Func) (4); \t dönüş t; } ' –

cevap

7

Sorun, MySet içinde göstermiş olduğunuz insert işlevleriyle ilgili değil. Sorun, atladığınızlardan biriyle. Özellikle:

[temp.deduct.call] kaynaktan
template< class InputIt > 
void insert(InputIt first, InputIt last); 

:

P elemanı işlevi tipi için bir işlev türü, işaretçi türü işlev ya da gösterici:
- bağımsız değişken ise Bir veya daha fazla fonksiyon şablonu içeren bir aşırı yükleme seti, parametre, çıkarılmamış bir bağlam olarak ile tedavi edilir.&std::set<int>::insert yana

parametresi olmayan bir çıkarılmış bağlam ve çözülemez, tam da böyle bir aşırı yük kümesidir. MySet örneğiniz, insert için bir işlev şablonu yüklemesi içermiyor, bu yüzden iyi çalışıyor. Bir tane eklerseniz, bunun da derlenemeyeceğini görürsünüz.

+0

Doğru cevap olduğunu düşünüyorum. Çok yakındım. – Nawaz

+0

Evet, bir 'template' işlevi ekleyerek [derlemez] (http://ideone.com/SF5EbB). Bu örnek için ilgisiz olduğunu düşünerek bu işlevi atladım :-). Asıl sorun için şık bir çözüm bulabilirseniz, yani bu kısıtlamalarla ReceiveFuncPtr() öğesini nasıl uygulayacağınız bir bonus olacaktır. – iammilind

+0

@iammilind Doğru türde yazmanız gerekir. Bu durumda, bu bir ağız dolusu: 'ReceiveFuncPtr (static_cast :: yineleyici, bool> (std :: set :: *) (const int &)> (& std :: set :: insert)) veya '' insert' gibi bir işlev şablonu olmayan bir sınıf yazabilirsiniz. – Barry