2013-02-12 22 views
5

Şu anda std::stringstream için bir sarmalayıcı yazıyorum ve tüm operator<< çağrılarımı sınıfım aracılığıyla std::stringstream'a iletmek istiyorum. Bu şimdi sadece (bu soruya teşekkürler: wrapper class for STL stream: forward operator<< calls), ama yine de onunla ilgili bir sorun var.iostream için C++ sarmalayıcı sınıfı, işleçle birlikte std :: endl gibi akış değiştiricilerini kullanın <<

en Aşağıdaki kod var diyelim:

class StreamWrapper { 
private: 
    std::stringstream buffer; 
public: 
    template<typename T> 
    void write(T &t); 

    template<typename T> 
    friend StreamWrapper& operator<<(StreamWrapper& o, T const& t); 

    // other stuff ... 
}; 


template<typename T> 
StreamWrapper& operator<<(StreamWrapper& o, T const& t) { 
    o.write(t); 
    return o; 
} 

template<typename T> 
void StreamWrapper::write(T& t) { 
    // other stuff ... 

    buffer << t; 

    // other stuff ... 
} 

Bunu şimdi ise: Bu sadece iyi çalışır

StreamWrapper wrapper; 
wrapper << "text" << 15 << "stuff"; 

. Ancak gibi akış değiştiricilerini kullanmak istiyorum, bu http://www.cplusplus.com/reference/ios/endl'a göre bir işlevdir, ben sadece derlemem.

StreamWrapper wrapper; 
wrapper << "text" << 15 << "stuff" << std::endl; 

Neden? Akış değiştiricilerini nasıl iletebilirim?

+0

derleme hatası nedir? –

+0

Bir işleve sahip olan işleç << << 'aşırı yükleri vardır ve daha sonra akışta bu işlevi çağırın: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt http: //en.cppreference .com/w/cpp/io/manip – BoBTFish

cevap

3

Bkz. this answer.

Sen ekstra iş biraz yapıyor gibi görünüyor

typedef std::ostream& (*STRFUNC)(std::ostream&); 

StreamWrapper& operator<<(STRFUNC func) // as a member, othewise you need the additional StreamWrappe& argument first 
{ 
    this->write(func); 
    return *this; 
} 
+0

@Mogria neden düzenleme? "STRFUNC" nesneleri işlevdir (işaretçiler), böylece doğrudan "ostream" üzerinde çağrılabilirler. – rubenvb

+0

Çünkü yazım yöntemimin içinden geçmesi gerekiyor çünkü içindeki diğer şeyler yüzünden. – MarcDefiant

2

isteyeceksiniz. Normalde kullanın:

modern derleyici ile
class StreamWrapper 
{ 
    // ... 
public: 
    template <typename T> 
    StreamWrapper& operator<<(T const& obj) 
    { 
     // ... 
    } 
}; 

, bütün beton türleri için bu gerektiği eser. Sorun, manipülatörlerin şablon işlevleri, olması ve derleyicinin kesinti şablonu argümanını yapamamasıdır. Solüsyon manipülatör türleri için şablon olmayan aşırı yükleri sağlamaktır:

StreamWrapper& operator<<(std::ostream& (*pf)(std::ostream&)) 
{ 
    // For manipulators... 
} 

StreamWrapper& operator<<(std::basic_ios<char>& (*pf)(std::basic_ios<char>&) 
{ 
    // For manipulators... 
} 

Tip kesinti manipülatörler için başarısız olur, ancak derleyici fonksiyon aşırı yük çözünürlüğü için bu bulacaktır.

(eğer std::setw(int) gibi şeyler için, daha eşit gerekebilir unutmayın.)

+0

R değeri referans desteğiniz varsa, mükemmel yönlendirme deyimi sorunu giderir mi? –

+0

@Tim Bunu düşünmüyorum. Elimi nasıl değiştireceğini bir türlü göremiyorum. Scott Meyer'e göre (kesinlikle güvendiğim), şablon isimleri mükemmel bir şekilde iletilemez (ve bir derleyicide nasıl uygulayabileceğinizi göremiyorum) ve manipülatörlerin hepsi şablon isimleridir. –

+0

Eğer bunu söyleseydi, o zaman ben de ona güvenirim. Hafızamda, evrensel referansların "her şeye bağlandığı" şeklindeki tekrarlanan ifadeleri vardı. –

İlgili konular