2015-02-07 22 views
7

std::ostream için genel bir operator<< ve herhangi bir yinelenen tür oluşturmaya çalışıyorum. C++ şablon operatörü eşleşme olarak bulunamadı

Bu

kodudur:
template <class T,template<class> class Iterable> inline std::ostream& operator<<(std::ostream& s,const Iterable<T>& iter){ 
    s << "[ "; 
    bool first=false; 
    for(T& e : iter){ 
     if(first){ 
      first=false; 
      s << e; 
     }else{ 
      s << ", " << e; 
     } 
    } 
    s << " ]"; 
    return s; 
} 

Ne yazık ki benim operatör bir vector<uint> için bir eşleşme olarak bulunmazsa ve derleyici operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) ile eşleştirmeye çalışır.

Tanınacak aşırı yükü nasıl değiştirebilirim?

+1

Başka sorun olmayan bir const 'T' ile bir 'const' kap yineleme deneyin olmasıdır. Bunun yerine 'T &&' veya 'T const &' kullanın. –

+3

Ayrıca gerçek –

cevap

4

sorununuza doğrudan çözüm yazmayı isterdim böylece vectoriki türleri değil, birinde bir şablon, olmasıdır:

çalışır, ancak biraz tatmin edici değil
template <typename... T, template <typename... > class Iterable> 
inline std::ostream& operator<<(std::ostream& os, const Iterable<T...>& iter) 
{ 
    s << "[ "; 
    bool first = true; // not false 
    for (const auto& e : iter) { 
     // rest as before 
    } 
    return s << " ]"; 
} 

- beri Şablon olan bazı şeyler yinelenemez ve şablon olmayan bazı şeylerdir. Ayrıca, aslında bizim çözeltide ya Iterable veya T gerekmez. Öyleyse nasıl herhangi Range alır şeyler yazmak hakkında - biz begin() ve end() olan bir şey olarak Range tanımlayın:

template <typename Range> 
auto operator<<(std::ostream& s, const Range& range) 
-> decltype(void(range.begin()), void(range.end()), s) 
{ 
    // as above, except our container is now named 'range' 
} 

buysa çok genel, o zaman yapabilirsiniz:

template <typename T> struct is_range : std::false_type; 
template <typename T, typename A> 
struct is_range<std::vector<T,A>> : std::true_type; 
// etc. 

template <typename Range> 
typename std::enable_if< 
    is_range<Range>::value, 
    std::ostream& 
>::type 
operator<<(std::ostream& s, const Range& range)  
+1

sayesinde ilk başlatmak gerekir. maalesef bu benim için çalışmaz, belki operatör çok genel olduğu için. 'işleç <<' için belirsiz aşırı yüklenme gibi hatalar çok olsun (işlenenler 'std :: stringstream {aka std :: basic_stringstream }' ve 'std :: string {aka std :: basic_string }' 'string' başlangıçta() ve bitiş() 'dir. – tly

+1

Sadece bir 'typename std :: enable_if :: value, std :: ostream &> :: type' yazıp' is_container' için bir tür özellik yazabilirsiniz. İstediğinizi yapar – Barry

+0

@Barry Henüz standardize edilmemiş olsa da, 'Range' adını kullanmayı tercih ederim. Yine de, aralık-tabanlı döngüden gereksinimlere sahibiz ve benzer bir şeyi taklit edebiliriz. özgür 'begin' ve' Sonu 'fonksiyonları (artı arama hileler). Range' 'yeniden adlandırıldı – dyp