2013-02-12 25 views
5

Tôi hiện đang viết trình bao bọc cho số std::stringstream và tôi muốn chuyển tiếp tất cả các cuộc gọi operator<< qua lớp học của tôi tới số std::stringstream. Điều này hoạt động tốt ngay bây giờ (nhờ câu hỏi này: wrapper class for STL stream: forward operator<< calls), nhưng vẫn còn một vấn đề với nó.Lớp trình bao bọc C++ cho iostream, sử dụng công cụ sửa đổi luồng như std :: endl với toán tử <<

Hãy nói rằng tôi có đoạn mã sau:

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 ... 
} 

Nếu bây giờ tôi làm điều này:

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

này hoạt động tốt. Nhưng nếu tôi muốn sử dụng các công cụ sửa đổi luồng như std::endl, là một chức năng theo http://www.cplusplus.com/reference/ios/endl, tôi chỉ đơn giản là không biên dịch.

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

Tại sao? Tôi có thể chuyển tiếp các công cụ sửa đổi luồng như thế nào?

+0

Lỗi biên dịch là gì? –

+0

Có quá tải của toán tử << 'có chức năng, và sau đó gọi hàm đó trên luồng: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt http: //en.cppreference .com/w/cpp/io/manip – BoBTFish

Trả lời

3

Xem this answer.

Bạn sẽ muốn

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 lý do chỉnh sửa? Đối tượng 'STRFUNC' là hàm (con trỏ), vì vậy chúng có thể được gọi trực tiếp trên' ostream'. – rubenvb

+0

bởi vì nó cần phải đi qua phương pháp viết của tôi, vì những thứ khác trong đó. – MarcDefiant

2

Bạn dường như đang làm một chút công việc phụ. Tôi thường sử dụng:

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

Với một trình biên dịch hiện đại, điều này nên làm việc cho tất cả loại bê tông. Vấn đề là các thao tác là các hàm mẫu, do đó trình biên dịch không thể thực hiện loại đối số mẫu khấu trừ. Giải pháp là để cung cấp không mẫu quá tải cho các loại của thao tác:

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

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

Loại khấu trừ sẽ thất bại cho các thao tác, nhưng trình biên dịch sẽ nhặt những để giải quyết tình trạng quá tải chức năng.

(Lưu ý rằng bạn có thể cần nhiều hơn, cho những thứ như std::setw(int).)

+0

Thành ngữ chuyển tiếp hoàn hảo có làm giảm bớt vấn đề nếu bạn có hỗ trợ tham chiếu giá trị r không? –

+0

@Tim Tôi không nghĩ vậy. Tôi không thấy tay nó sẽ thay đổi thế nào. Theo Scott Meyer (người mà tôi tin tưởng), các tên mẫu không thể được chuyển tiếp hoàn hảo (và tôi không thấy cách bạn có thể thực hiện nó trong trình biên dịch), và các trình điều khiển là tất cả các tên mẫu. –

+0

Nếu anh ấy nói vậy, tôi cũng tin tưởng điều đó. Tôi chỉ có trong bộ nhớ của tôi những câu nói lặp đi lặp lại của ông rằng những tham chiếu phổ quát "liên kết với mọi thứ". –