I recently did some experiments which tested how well the "auto_ptr" class template works with a current version of ROOT. The purpose of this e-mail is to briefly post my results. My results are that, as of ROOT version 2.22.10 (the most current version of ROOT as I write this), "auto_ptr" can be used interactively with cint in a limited way with a few caveats: 1) Only one of the two forms of calling the "auto_ptr" constructor works: auto_ptr<Foo> foo( new Foo() ); // OK auto_ptr<Foo> foo = new Foo(); // broken 2) "operator->" does not work. Therefore, as long as you stick to "operator*" for accessing your heap based objects, "auto_ptr" should work well for you. However, not having "operator->" doesn't make the "auto_ptr" smart pointer very smart. Perhaps the constructor and "operator->" problem are fixable in a straight forward way for Masaharu. Therefore, instead of using an "auto_ptr" like this: auto_ptr<Foo> foo( new Foo() ); foo->Print(); You will have to use it like this: auto_ptr<Foo> foo( new Foo() ); (*foo).Print(); or this: auto_ptr<Foo> foo0( new Foo() ); Foo& foo1 = *foo0; foo1.Print(); Finally, those parts of "auto_ptr" that do work also work well from both interpreted and compiled code. The full package which demonstrates the use of "auto_ptr" with ROOT is available at ftp://ftp.slac.stanford.edu/users/langston/root/root-auto_ptr-0.01.tar.gz. I have also attached the README from this package to this e-mail, which describes the problems in a bit more detail. -- Matthew D. Langston SLD, Stanford Linear Accelerator Center langston@SLAC.Stanford.EDU ROOT 2.22.10 and auto_ptr ************************* Introduction ------------ The "auto_ptr" class template is an extremely important and useful class that all C++ programmers, both novice and expert alike, should not only know how to use, but should use on a regular basis whenever using the heap. The use of "auto_ptr" is particularly important for ROOT users because many of the scripting habits we pick up in our interactive use of ROOT are "no-nos" when it comes time to move our code into compiled applications and libraries. For example, taking advantage of cint's useful garbage collecting abilities is fine for simple interactive use, but ignoring, or forgetting, your responsibility to manage your use of the heap in compiled code leads to memory leaks and hard-to-find bugs. The use of "auto_ptr" can go a long way in helping you automatically manage your use of the heap. Results and Summary ------------------- I recently did some experiments which tested how well the "auto_ptr" class template works with a current version of ROOT. My results are that, as of ROOT version 2.22.10 (the most current version of ROOT as I write this), "auto_ptr" can be used interactively with cint in a limited way with a few caveats: 1) Only one of the two forms of calling the "auto_ptr" constructor works: auto_ptr<Foo> foo( new Foo() ); // OK auto_ptr<Foo> foo = new Foo(); // broken 2) "operator->" does not work. Therefore, as long as you stick to "operator*" for accessing your heap based objects, "auto_ptr" should work well for you. However, not having "operator->" doesn't make the "auto_ptr" smart pointer very smart. Perhaps this is a straight forward fix for Masaharu. Therefore, instead of using an "auto_ptr" like this: auto_ptr<Foo> foo( new Foo() ); foo->Print(); You will have to use it like this: auto_ptr<Foo> foo( new Foo() ); (*foo).Print(); or this: auto_ptr<Foo> foo0( new Foo() ); Foo& foo1 = *foo0; foo1.Print(); Finally, those parts of "auto_ptr" that do work also work well from both interpreted and compiled code. Building and Testing Yourself ----------------------------- This tiny package, "root-auto_ptr", demonstrates some simple experiments of using "auto_ptr" with ROOT. Perhaps this package might be useful to the ROOT developers as they work on the template support in cint, and particularly as they work on adding batter support for the "auto_ptr" class template. To build and run the examples, do the following: $ gunzip -c root-auto_ptr-0.01.tar.gz | tar -xpvf - $ mkdir root-auto_ptr-0.01.build $ cd root-auto_ptr-0.01.build $ ../root-auto_ptr-0.01/configure $ make $ make check I have also provided the file `Makefile.manual' for "stand-alone" operation. It provides a subset of the functionality in the Autoconf, Automake and Libtool files, but is enough to build and run the tests in a directory separate from the source. For example, you would use this Makefile as follows: $ ln -s /blah/blah/blah/Makefile.manual Makefile $ make check The point of providing this Makefile is to make it easier to experiment with the examples. The Autoconf, Automake and Libtool files provide a lot of additional functionality that you don't need if you just want to build and run the examples. Your build times will be faster if you use this Makefile, but you may have to edit a few of the "System" and "ROOT" macros to get the examples to build properly. Running "make check" runs both compiled versions, and "cint interpreted" versions, of the tests. NOTE: cint always returns success (i.e. exit code 0), even when interpreted code fails. This makes it difficult to write a ROOT testsuite, so you will have to visually scan the output of the tests "by eye" to determine which of the tests actually fail. Nitty Gritty Details for ROOT Developers ---------------------------------------- The current problem of using "auto_ptr" interactively in cint is that "operator->" is not resolved properly. As in all implementations of "smart pointers", "operator->" must ultimately forward the request to the pointee. For example, this is how "operator->" is overloaded in "auto_ptr" (see the files `auto_ptr.hxx' and `auto_ptr.ixx' for the full implementation): template< class T > inline T* auto_ptr< T >::operator->() const { return pointee; } Now consider the following code, which, given the implementation of "operator->" above, should call the member function "Foo::Print()" of the object "foo": auto_ptr<Foo> foo( new Foo() ); foo->Print(); However, cint doesn't appear to resolve the call to "operator->" properly, as evidenced by this typical cint error message: Error: Can't call auto_ptr<Foo>::Print() in current scope ... I have tried the following combinations of using the "operator->" member function of "auto_ptr" with ROOT: +------------------------+----------------------------+ | auto_ptr<> interpreted | auto_ptr<Foo> pre-compiled | +------------------------+------------------------+----------------------------+ | | | | | class Foo interpreted | NO | NO | | | | | +------------------------+------------------------+----------------------------+ | | | | | class Foo pre-compiled | NO | YES | | | | | +------------------------+------------------------+----------------------------+ NOTES: 1) "NO" means that the combination *does not* work with ROOT. 2) "YES" means that the combination *does* work with ROOT. 3) The class "auto_ptr" was taken from Scott Meyers, "More Effective C++", 1st edition, (Addison-Wesley, 1996). I have been using this class successfully in compiled projects for many years. However, since it is documented that cint doesn't currently support "explicit" constructors nor template member functions, I conditionalized these two features out of the implementation of "auto_ptr" so that it could in principle be used by cint. 4) The class "Foo" (and classes "Bar" and "Baz" as well) are just simple dummy classes whose only purpose is to experiment with instantiating an "auto_ptr" with a user-defined type. 5) In the table above, "interpreted" means that the class is parsed by cint (i.e. the class does not reside in a shared library). 6) In the table above, "pre-compiled" means that the class is compiled and loaded into cint from a shared library. This means that "auto_ptr<Foo>" was instantiated and compiled in the same spirit as some of the new pre-compiled STL containers in recent versions of ROOT (e.g. "vector<int>"). Manifest -------- If you want to delve into the examples more deeply, then you will want to look at the files: .rootrc ROOT configuration file for running the test macros through ROOT (i.e. test_n.cxx, where "n" runs from 01 through 07). Bar.cxx \ Bar.hxx \ The classes "Foo", "Bar" and "Baz are just Baz.cxx \ simple dummy classes whose only purpose is to Baz.hxx / experiment with instantiating an "auto_ptr" with Foo.cxx / a user-defined type: Foo.hxx / Makefile.manual Useful Makefile for building a shared library of the above files. README This file. auto_ptr.hxx auto_ptr definition file auto_ptr.ixx auto_ptr implementation file auto_ptr_LinkDef.h Common instantiations of auto_ptr<> to put into a cint dictionary (i.e. "auto_ptr<Foo>" and "auto_ptr<Bar>"). For the following files, "n" runs from 01 through 07. test_n.cxx auto_ptr test files test_n.sh shell script to run the `test_n.cxx' as a ROOT macro. Miscellany ---------- These experiments were done on a Pentium III system running Linux (i.e. i686-pc-linux-gnu). The system's exact configuration is: Machine configuration with bug ------------------------------ RedHat Linux 6.0 Intel kernel 2.2.5 (rpm version kernel-2.2.5-22) glibc 2.1.1 (rpm version glibc-2.1.1-6) egcs 1.1.2 (rpm version egcs-1.1.2-12) binutils 2.9.1.0.23 (rpm version binutils-2.9.1.0.23-1 ROOT 2.22.10 -- Matthew D. Langston <langston@SLAC.Stanford.EDU> 1999-08-13
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:38 MET