2011-12-14 17 views
6

Tôi muốn thực hiện lớp MyCout, có thể cung cấp khả năng endl tự động, ví dụ: mã nàymycout endl tự động

MyCout mycout; 
mycout<<1<<2<<3; 

đầu ra

123 
//empty line here 

Có thể thực hiện lớp học với chức năng như vậy?


UPDATE: Soulutions không nên như thế MyCout()<<1<<2<<3; ví dụ: họ nên được mà không cần tạo tạm thời đối tượng

+0

Tất nhiên điều đó có thể xảy ra, bạn có câu hỏi cụ thể hơn về cách viết lớp và điều hành quá tải của riêng bạn? – TJD

+0

Tại sao bạn muốn làm điều này? –

+0

Đây là một vấn đề thú vị. Như tôi hiểu nó endl được gắn lên với đỏ bừng. Chưa kể rằng phương thức nạp chồng của toán tử sẽ phải biết điều gì đó xảy ra sau khi nó trả về để biết endl nằm ở đâu. –

Trả lời

2

này chỉ đơn giản là một biến thể của Rob's answer, mà không sử dụng các đống. Đó là một thay đổi đủ lớn mà tôi không muốn chỉ thay đổi câu trả lời của mình mặc dù

struct MyCout { 
    MyCout(std::ostream& os = std::cout) : os(os) {} 
    struct A { 
    A(std::ostream& r) : os(r), live(true) {} 
    A(A& r) : os(r.os), live(true) {r.live=false;} 
    ~A() { if(live) {os << std::endl;} } 
    std::ostream& os; 
    bool live; 
    }; 
    std::ostream& os; 
}; 

template <class T> 
MyCout::A& operator<<(MyCout::A& a, const T& t) { 
    a->os << t; 
    return a; 
} 

template<class T> 
MyCout::A operator<<(MyCout& m, const T& t) { return MyCout::A(os) << t; } 

int main() { 
    MyCout mycout; 
    mycout << 1 << 2 << 3; 
    mycout << 3 << 4 << 5; 
    MyCout mycerr(std::cerr); 
    mycerr << 6 << "Hello, world" << "!"; 
} 
+0

Bạn có thể chắc chắn rằng việc cắt bỏ bản sao sẽ không xảy ra khi trả về từ 'toán tử << (MyCout &, const T &)'? –

+1

@Rob: Không, nhưng nếu tôi làm đúng, điều đó không làm thay đổi hành vi của chương trình. Tôi sử dụng 'bool live' để mô phỏng một hàm khởi tạo. –

8

Bạn có thể sử dụng các destructor của một đối tượng tạm thời để tuôn ra những dòng suối và in một dòng mới. Hệ thống gỡ lỗi Qt thực hiện điều này và this answer mô tả cách thực hiện.

+0

Tôi cũng nghĩ vậy. Cùng với ngữ nghĩa di chuyển cho các hoạt động bên trong. –

+0

Bạn chỉ có thể sử dụng từng đối tượng cho một tuyên bố đầu ra, điều này có vẻ cực kỳ tối ưu. –

+0

@Autopulated, vâng, tôi biết về biến thể này, nhưng tôi đã viết rằng nó phải nhìn theo cách sau: 'MyCout mycout; mycout << ... 'tức là đối tượng tạm thời không phải là giải pháp – eXXXXXXXXXXX2

7

Các công trình sau đây trong C++ 11:

#include <iostream> 

struct myout_base { }; 
struct myout 
{ 
    bool alive; 
    myout() : alive(true) { } 
    myout(myout && rhs) : alive(true) { rhs.alive = false; } 
    myout(myout const &) = delete; 
    ~myout() { if (alive) std::cout << std::endl; } 
}; 

template <typename T> 
myout operator<<(myout && o, T const & x) 
{ 
    std::cout << x; 
    return std::move(o); 
} 

template <typename T> 
myout operator<<(myout_base &, T const & x) 
{ 
    return std::move(myout() << x); 
} 

myout_base m_out; // like the global std::cout 

int main() 
{ 
    m_out << 1 << 2 << 3; 
} 

Với công việc nhiều hơn, bạn có thể thêm một tham chiếu đến các dòng sản lượng thực tế.

+0

Bây giờ đó là một giải pháp gọn gàng. – James

+0

Chỉ có thể sử dụng C++ rõ ràng?) – eXXXXXXXXXXX2

+4

Có. I * am * chỉ sử dụng rõ ràng C++ :-) –

1

Nếu bạn cần phải tránh C++ 11 tính năng:

#include <iostream> 
#include <sstream> 
#include <memory> 

struct MyCout { 
    MyCout(std::ostream& os = std::cout) : os(os) {} 
    struct A { 
    A(std::ostream& os) : os(os) {} 
    A() : os(os) {} 
    ~A() { os << std::endl; } 
    std::ostream& os; 
    }; 
    std::ostream& os; 
}; 

template <class T> 
const std::auto_ptr<MyCout::A>& 
operator<<(const std::auto_ptr<MyCout::A>& a, const T& t) { 
    a->os << t; 
    return a; 
} 

template<class T> 
const std::auto_ptr<MyCout::A> 
operator<<(MyCout& m, const T& t) { 
    std::auto_ptr<MyCout::A> p(new MyCout::A(m.os)); 
    p << t; 
    return p; 
} 

int main() { 
    MyCout mycout; 
    mycout << 1 << 2 << 3; 
    mycout << 3 << 4 << 5; 
    MyCout mycerr(std::cerr); 
    mycerr << 6 << "Hello, world" << "!"; 
} 
+0

Đúng, chỉ cần tạo một lớp bên trong và trả về giá trị thay vì bằng tham chiếu trên toán tử << ban đầu, sau đó flush/endl trên destructor của đối tượng đó. Tự động tạo đối tượng tạm thời cho bạn. –

+0

@Rob: Đây là những gì tôi sẽ làm, ngoại trừ tôi sẽ sử dụng một bool để xem nếu nó còn sống thay vì nhấn cấp phát. –

+0

@ebyrob: Không thể trả về theo giá trị, bởi vì nó có thể tạo một bản sao, và sau đó xóa bản sao tạm thời, gây thêm xả. –