www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C++ istream / ostream equivalent ?

reply vincent picaud <vincent.picaud laposte.net> writes:
Is there a canonical way to take into account a new type for I/O using the std
phobos library ?

To be clear I do not know how to translate something like this (in C++)  in D :

#include <iostream>

class A {};

std::ostream& operator<<(std::ostream& out,const A& a)
{
  out << "\nscreen output routine here\n";
  return out;
}

int main()
{
  A a;
  std::cout << a;
}

Do I have to overload some writeln functions ?

any help is welcome :)
Dec 01 2010
next sibling parent reply Matthias Pleh <gonzo web.net> writes:
Am 01.12.2010 16:51, schrieb vincent picaud:
 Is there a canonical way to take into account a new type for I/O using the std
phobos library ?

 To be clear I do not know how to translate something like this (in C++)  in D :

 #include<iostream>

 class A {};

 std::ostream&  operator<<(std::ostream&  out,const A&  a)
 {
    out<<  "\nscreen output routine here\n";
    return out;
 }

 int main()
 {
    A a;
    std::cout<<  a;
 }

 Do I have to overload some writeln functions ?

 any help is welcome :)
I would make it this way: module test; import std.stdio; class A{} class B{ string toString() {return "screen output routine here";}} int main(string[] args) { A a=new A; B b=new B; writeln(a.toString()); writeln(b.toString()); return 0; } output:
 test.A
 screen output routine here
Base-class of all classes is object with have a default-toString() method, which gives the module.classname. So you can overwrite this method.
Dec 01 2010
next sibling parent reply vincent picaud <vincent.picaud laposte.net> writes:
Matthias Pleh Wrote:

 Am 01.12.2010 16:51, schrieb vincent picaud:
 Is there a canonical way to take into account a new type for I/O using the std
phobos library ?

 To be clear I do not know how to translate something like this (in C++)  in D :

 #include<iostream>

 class A {};

 std::ostream&  operator<<(std::ostream&  out,const A&  a)
 {
    out<<  "\nscreen output routine here\n";
    return out;
 }

 int main()
 {
    A a;
    std::cout<<  a;
 }

 Do I have to overload some writeln functions ?

 any help is welcome :)
I would make it this way: module test; import std.stdio; class A{} class B{ string toString() {return "screen output routine here";}} int main(string[] args) { A a=new A; B b=new B; writeln(a.toString()); writeln(b.toString()); return 0; } output: > test.A > screen output routine here Base-class of all classes is object with have a default-toString() method, which gives the module.classname. So you can overwrite this method.
Thank you for your reply and yes that works :) Now i m facing with the following problem, what is the trick for input stream ? ( something like std::istream& operator>>(std::istream& in,A& a) { // A.someData << in; return in; } in C++ ) I m thinking of the situation when we want to load some data from a file. The toString() trick is okay for saving the object... but how to load it back (something like fromString(char[]) would do the job but it does not exist in Object) ? Anyway thank you, you solved half of my problem :)
Dec 01 2010
parent reply Matthias Pleh <gonzo web.net> writes:
 Thank you for your reply and yes that works :)

 Now i m facing with the following problem, what is the trick for input stream ?

 ( something like

 std::istream&  operator>>(std::istream&  in,A&  a)
 {
    //  A.someData<<  in;
    return in;
 }

 in C++ )

 I m thinking of the situation when we want to load some data from a file.

 The toString() trick is okay for saving the object... but how to load it back
(something like fromString(char[]) would do the job but it does not exist in
Object) ?

 Anyway thank you, you solved half of my problem :)
Ther are many posibilities, depending on your further needs! Just have a look at the online dokumentation: http://www.digitalmars.com/d/2.0/phobos/phobos.html But my first try would be such .. (note: I've leaved out error-handling ...) module test; import std.stdio; import std.file; class A { void writeToFile() { std.file.write("sample.txt",someData); } void readFromFile() { someData=cast(string)read("sample.txt"); } void clear() { someData="n/A\n"; } string toString() { return someData; } private: string someData="Just some data. With anohter line of date. Even more data.!"; } int main(string[] args) { A a=new A; a.writeToFile(); a.clear(); writeln(a); a.readFromFile(); writeln(a); return 0; }
Dec 01 2010
parent reply vincent picaud <vincent.picaud laposte.net> writes:
Matthias Pleh Wrote:

 
 Thank you for your reply and yes that works :)

 Now i m facing with the following problem, what is the trick for input stream ?

 ( something like

 std::istream&  operator>>(std::istream&  in,A&  a)
 {
    //  A.someData<<  in;
    return in;
 }

 in C++ )

 I m thinking of the situation when we want to load some data from a file.

 The toString() trick is okay for saving the object... but how to load it back
(something like fromString(char[]) would do the job but it does not exist in
Object) ?

 Anyway thank you, you solved half of my problem :)
Ther are many posibilities, depending on your further needs! Just have a look at the online dokumentation: http://www.digitalmars.com/d/2.0/phobos/phobos.html But my first try would be such .. (note: I've leaved out error-handling ...) module test; import std.stdio; import std.file; class A { void writeToFile() { std.file.write("sample.txt",someData); } void readFromFile() { someData=cast(string)read("sample.txt"); } void clear() { someData="n/A\n"; } string toString() { return someData; } private: string someData="Just some data. With anohter line of date. Even more data.!"; } int main(string[] args) { A a=new A; a.writeToFile(); a.clear(); writeln(a); a.readFromFile(); writeln(a); return 0; }
thank you for all your answers. I understand the approach, but in the same time, I have the feeling that the C++ way is more convenient. Look in C++ , to define I/O for A, you do not have to modify your class A and simply have to overload two functions: std::ostream& operator<<(std::ostream& out,const A& a) std::istream& operator>>(std::istream& in,A& a) moreover this smoothly extend the I/O C++ framework without other side effect. I was expecting to find a similar mecanism in D/Phobos Perhaps by overloading some read(), write() functions of the Phobos library, but I do not know if it is "moral" to do that and which phobos functions are concerned... IMHO there is a documentation hole here
Dec 02 2010
next sibling parent reply =?ISO-8859-1?Q?Pelle_M=E5nsson?= <pelle.mansson gmail.com> writes:
On 12/02/2010 09:05 AM, vincent picaud wrote:
 Matthias Pleh Wrote:

 Thank you for your reply and yes that works :)

 Now i m facing with the following problem, what is the trick for input stream ?

 ( something like

 std::istream&   operator>>(std::istream&   in,A&   a)
 {
     //  A.someData<<   in;
     return in;
 }

 in C++ )

 I m thinking of the situation when we want to load some data from a file.

 The toString() trick is okay for saving the object... but how to load it back
(something like fromString(char[]) would do the job but it does not exist in
Object) ?

 Anyway thank you, you solved half of my problem :)
Ther are many posibilities, depending on your further needs! Just have a look at the online dokumentation: http://www.digitalmars.com/d/2.0/phobos/phobos.html But my first try would be such .. (note: I've leaved out error-handling ...) module test; import std.stdio; import std.file; class A { void writeToFile() { std.file.write("sample.txt",someData); } void readFromFile() { someData=cast(string)read("sample.txt"); } void clear() { someData="n/A\n"; } string toString() { return someData; } private: string someData="Just some data. With anohter line of date. Even more data.!"; } int main(string[] args) { A a=new A; a.writeToFile(); a.clear(); writeln(a); a.readFromFile(); writeln(a); return 0; }
thank you for all your answers. I understand the approach, but in the same time, I have the feeling that the C++ way is more convenient. Look in C++ , to define I/O for A, you do not have to modify your class A and simply have to overload two functions: std::ostream& operator<<(std::ostream& out,const A& a) std::istream& operator>>(std::istream& in,A& a) moreover this smoothly extend the I/O C++ framework without other side effect. I was expecting to find a similar mecanism in D/Phobos Perhaps by overloading some read(), write() functions of the Phobos library, but I do not know if it is "moral" to do that and which phobos functions are concerned... IMHO there is a documentation hole here
What you want is the new writeTo system for output. For input, a readFrom would be symmetrical and make sense :-) To actually use it, you would just do myFile.write(your, stuff, etc); For now, you can stringify using toString(). No way to read yet, except to!int, etc.
Dec 02 2010
parent vincent picaud <vincent.picaud laposte.net> writes:
Pelle Månsson Wrote:

 On 12/02/2010 09:05 AM, vincent picaud wrote:
 Matthias Pleh Wrote:

 Thank you for your reply and yes that works :)

 Now i m facing with the following problem, what is the trick for input stream ?

 ( something like

 std::istream&   operator>>(std::istream&   in,A&   a)
 {
     //  A.someData<<   in;
     return in;
 }

 in C++ )

 I m thinking of the situation when we want to load some data from a file.

 The toString() trick is okay for saving the object... but how to load it back
(something like fromString(char[]) would do the job but it does not exist in
Object) ?

 Anyway thank you, you solved half of my problem :)
Ther are many posibilities, depending on your further needs! Just have a look at the online dokumentation: http://www.digitalmars.com/d/2.0/phobos/phobos.html But my first try would be such .. (note: I've leaved out error-handling ...) module test; import std.stdio; import std.file; class A { void writeToFile() { std.file.write("sample.txt",someData); } void readFromFile() { someData=cast(string)read("sample.txt"); } void clear() { someData="n/A\n"; } string toString() { return someData; } private: string someData="Just some data. With anohter line of date. Even more data.!"; } int main(string[] args) { A a=new A; a.writeToFile(); a.clear(); writeln(a); a.readFromFile(); writeln(a); return 0; }
thank you for all your answers. I understand the approach, but in the same time, I have the feeling that the C++ way is more convenient. Look in C++ , to define I/O for A, you do not have to modify your class A and simply have to overload two functions: std::ostream& operator<<(std::ostream& out,const A& a) std::istream& operator>>(std::istream& in,A& a) moreover this smoothly extend the I/O C++ framework without other side effect. I was expecting to find a similar mecanism in D/Phobos Perhaps by overloading some read(), write() functions of the Phobos library, but I do not know if it is "moral" to do that and which phobos functions are concerned... IMHO there is a documentation hole here
What you want is the new writeTo system for output. For input, a readFrom would be symmetrical and make sense :-) To actually use it, you would just do myFile.write(your, stuff, etc); For now, you can stringify using toString(). No way to read yet, except to!int, etc.
Yes, that is exactly what I want :) Thanks
Dec 02 2010
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
vincent picaud wrote:
 Matthias Pleh Wrote:
 class A
 {
[...]
      string toString()   { return someData;  }
 I have the feeling that the C++ way is more convenient.

 Look in C++ , to define I/O for A, you do not have to modify
 your class A and simply have to overload two functions:

 std::ostream& operator<<(std::ostream& out,const A& a)
 std::istream&  operator>>(std::istream&  in,A&  a)
Yes but those two functions are actually logical parts of the class's interface. Besides, in many cases a 'friend' declaration is needed. Tangentially, operator>> is overrated because it requires a complete object to work on. I find it exremely rare to input on top of an existing object, which would also require a default constructor; and being forced to write a default constructor is unpractical in some cases. Reading from a stream should have been designed to return a constructed object: auto a = readFrom!A(some_input); or as a static member function: auto a = A.readFrom(some_input); Ali
Dec 02 2010
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.12.2010 20:11, Matthias Pleh wrote:
 Am 01.12.2010 16:51, schrieb vincent picaud:
 Is there a canonical way to take into account a new type for I/O 
 using the std phobos library ?

 To be clear I do not know how to translate something like this (in 
 C++)  in D :

 #include<iostream>

 class A {};

 std::ostream&  operator<<(std::ostream&  out,const A&  a)
 {
    out<<  "\nscreen output routine here\n";
    return out;
 }

 int main()
 {
    A a;
    std::cout<<  a;
 }

 Do I have to overload some writeln functions ?

 any help is welcome :)
I would make it this way: module test; import std.stdio; class A{} class B{ string toString() {return "screen output routine here";}} int main(string[] args) { A a=new A; B b=new B; writeln(a.toString()); writeln(b.toString());
Or even more implicit version, since writeln and the likes recognize toString: writeln(a); writeln(b);
     return 0;
 }

 output:
 test.A
 screen output routine here
Base-class of all classes is object with have a default-toString() method, which gives the module.classname. So you can overwrite this method.
Well there is a relatively new proposal which aims to replace toString with more eficient and flexible function (and was generally accepted): http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP9 -- Dmitry Olshansky
Dec 01 2010
parent Matthias Pleh <gonzo web.net> writes:
 Or even more implicit version, since writeln and the likes recognize
 toString:
 writeln(a);
 writeln(b);
[...]
 Well there is a relatively new proposal which aims to replace toString
 with more eficient and flexible function (and was generally accepted):
 http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP9
thanks I wasn't aware of that. :)
Dec 01 2010
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Matthias Pleh wrote:

 class B{ string toString() {return "screen output routine here";}}
Isn't the 'override' keyword required? (Perhaps required only in D2?) I find string.format very helpful in toString() member functions. Finally, I still don't know whether the 'const'ness of the member function is required, allowed, or completely wrong. :) import std.string; class A { override string toString() const { return format("My %s formatted string: %s", "lovely", 42); } } Ali
Dec 01 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, December 01, 2010 11:40:11 Ali =C3=87ehreli wrote:
 Matthias Pleh wrote:
  > class B{ string toString() {return "screen output routine here";}}
=20
 Isn't the 'override' keyword required? (Perhaps required only in D2?)
=20
 I find string.format very helpful in toString() member functions.
=20
 Finally, I still don't know whether the 'const'ness of the member
 function is required, allowed, or completely wrong. :)
=20
 import std.string;
=20
 class A
 {
      override string toString() const
      {
          return format("My %s formatted string: %s", "lovely", 42);
      }
 }
=20
 Ali
override is required if you compile with -w. If you don't use -w, the compi= ler=20 won't complain, but I'm not sure that it actually overrides the function in= that=20 case. So, yes override should be there. Object's toString() is not currently const-correct. It isn't const. So,=20 currently, when overriding toString(), you don't have to make it const. How= ever,=20 you _can_ make it const if you want to (and honestly, Object's toString()=20 _should_ be const; it's just among the changes that need to be made to Obje= ct to=20 make it properly const-correct: http://is.gd/i3KUJ ). Making a non-const=20 function const when overriding it is adding guarantees, not loosening them,= so=20 it works. Be forewarned, however, that because of bug http://is.gd/i3Lc2 ), _struct_'= s=20 toString() cannot be const (or at least, you need a non-const version in=20 addition to a const one if you have a const one). Classes don't have that=20 problem though. =2D Jonathan M Davis
Dec 01 2010
next sibling parent Matthias Pleh <gonzo web.net> writes:
Am 01.12.2010 20:59, schrieb Jonathan M Davis:
 override is required if you compile with -w. If you don't use -w, the compiler
 won't complain, but I'm not sure that it actually overrides the function in
that
 case. So, yes override should be there.
I've just tried it out. It is really overridden, even if the override keyword is missing. But the cool thing with override is, when you use it, but mistpyed the methodname or someone else changed one of the methods, the compiler know, you wanted to override something, but there isn't anymore to override! So yes, you're right, override should be used!!
Dec 01 2010
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 override is required if you compile with -w. If you don't use -w, the compiler 
 won't complain, but I'm not sure that it actually overrides the function in
that 
 case. So, yes override should be there.
override will become obligatory, Andrei and Walter agree with this change, so always (when possible) use it. See also bug 3836. Bye, bearophile
Dec 01 2010
prev sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
I'm currently looking at ways to improve std.conv.to. And this might be a good
area to improve std.conv.parse.

For example parse could be made to look for a method static readFrom!(T)()
if(isSomeString!T) and maybe to should take advantage of it.

auto foo = to!A(someString);

I'd have to require the entire string be used to convert, while parse would not
(consistent with other differences). So you'd likely use parse:

try while(true) {
    a[i++] = parse!A(someString);
} catch ...

Opinions?
Dec 02 2010