2012-09-03 32 views
6

derlemek için türetilmiş bir sınıf adını eşdeğer bir sınıfla değiştirme başarısız oluyor Yinelenen ve bir işlevi kabul eden bir şablonlu işlev oluşturmaya çalışıyorum, böylece geçirilen işlev dolaylı olarak bir std::function Uygun tipte (böylece hem tam fonksiyonlarla hem de lambdalarla kullanılmasına izin verir).(g ++ 4.7.1)

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <typeinfo> 


template<typename T> 
void bar(const T & base, std::function<bool(int)> f) // works 
//void bar(const T & base, std::function<bool(typename T::iterator::value_type)> f) // fails to compile 
{ 
    std::cout << ((typeid(std::function<bool(int)>) == typeid(std::function<bool(typename T::iterator::value_type)>))?"identical":"distinct") << std::endl; 
} 

bool filter(int x) { return x%2==0; } 

int main() { bar(std::vector<int> {0, 1}, filter); } 

bu identical üretir g++-4.7 -std=c++11 -o itest itest.cpp ile Derleyen:

İşte kod. Eğer yorumsuz hat 10 ve yorum hattı 9 ve yukarıdaki gibi derlemek

yerine derleme ben değiştirilmemiş sürümü Xcode (uygun seçenekleri ayarladıktan) ile başarılı belirtmeliyiz

g++-4.7 -std=c++11 -Wall -Werror -o itest itest.cpp 
itest.cpp: In function 'int main()': 
itest.cpp:16:53: error: no matching function for call to 'bar(std::vector<int>, bool (&)(int))' 
itest.cpp:16:53: note: candidate is: 
itest.cpp:9:10: note: template<class T> void bar(const T&, std::function<bool(typename T::iterator::value_type)>) 
itest.cpp:9:10: note: template argument deduction/substitution failed: 
itest.cpp:16:53: note: mismatched types 'std::function<bool(typename T::iterator::value_type)>' and 'bool (*)(int)' 

ile başarısız ama ben d Mümkünse g ++ ile yapışmayı tercih edin. Yanlış bir şey mi yapıyorum yoksa g ++ olarak bilinen bir hata mı?

cevap

5

Üzgünüz, ama kod kodunuzda. Bu eşdeğerdir:

template<typename T> struct S { template<typename U> S(const U &); }; 
template<typename T> void bar(T, S<T>); 
int main() { bar(5, 6); } 

sorunu olduğu şablon argümanı kesinti/yerine, bir şablon argümanı (doğrudan veya bir bağımlı tip oluşturmada) daha sonra her iki argüman tam olarak eşleşmesi gerekir birden fazla argüman görünürse; kullanıcı tanımlı dönüşümler, türün ne olması gerektiğine dair bir argümandan belirgin olsa bile, dikkate alınmaz.

Burada kullanıcı tanımlı dönüşüm, std::function<...>'un örtük kurucusudur. - o zaman derlemek olacak Sen işaretçi işlevi için ikinci aşırı ihtiyaç

template<typename T> 
void bar_impl(const T & base, std::function<bool(typename T::iterator::value_type)> f) 
{ 
    std::cout << ((typeid(std::function<bool(int)>) == typeid(std::function<bool(typename T::iterator::value_type)>))?"identical":"distinct") << std::endl; 
} 

template<typename T, typename F> 
void bar(const T & base, F &&f) 
{ 
    bar_impl<T>(base, std::forward<F>(f)); 
} 
+0

Huh, teşekkürler. Bir başka (daha da korkunç) geçici bir çözüm geliştirdim, biri arayanın ikinci türden bahsetmesini veya türetmesini gerektirmiyordu. – Bakkot

+0

Oops, [link] 'i (https://gist.github.com/a172651b93dc4670f295) unuttu. Her ikisini de okumak istemeyen insanlar için, aslında bu bir şeydir. – Bakkot

2

:

Olası düzeltme (bar<int> gibi) açıkça bar örneğini veya yardımcı işlevine gönderme olacaktır. (Işlev signutre içinde türlerini uymayan birkaç T) ecatmur tarafından açıklanan sorunu için etrafında

void bar(const T & base, bool(*f)(typename T::value_type)){ 
    std::cout << "ptr func\n"; 
} 

Work: std::function alışkanlık işe Örtülü döküm bunu gibi tanımlanır identity yapı, diğer T sarabilirsiniz:

Daha sonra derleyici bu T'leri tür kesintisi için yok sayar.