Christian <christians / syd.microforte.com.au> wrote: >Hi Josh, > >> References and containers can do the trick as well. For instance, take >> the following scenario: >> >> You create some sort of sorted container that holds >> complex objects by value. You lookup one of those objects >> and you want to do a number of operations involving one of >> its subparts. For efficiency, get a reference to that >> sub-part, so you don't need to keep asking for it or >> make an extra copy. Then, in a moment of blindness, >> some result causes you to insert a new item in >> the container. You may very well now have an >> invalid reference. >I don't intend to argue pedantics, but there are no sorted containers that >allow mutable access to its member elements: set<Ty>::iterator is a synonym >for set<Ty>::const_iterator. Even so, I take your point -- if you modify a >container whilst you are traversing it, you are asking for trouble. I was talking about a case where the container (not necessarily a std container) is sorted by keys and you are modifying its data fields. That is very common. The issue I had in mind wasn't related to losing the place of the iterator (which most people know is a nono) but simply that assignment operations might take place as a result of an insertion which have the effect of silently deallocating and reallocating some memory, swapping it around. The swapping is correct relative to the external semantics of the container, but the poor programmer is referencing a hunk of memory that 'don't work no more'. >Yes, >I've done this before and yes it is difficult to find the problem. Using >smart pointers helps. So does simply not mutating a container that you are >iterating over. If banging your head against a wall hurts, my best advice is >to stop banging your head against the wall. The point of this part of the discussion was that there are practical consequences to the lack of type safety in C++, for both "expert" and novices. Your claim that one can avoid that by using containers, references, and no casts, is not true in theory or in practice. >> >e) You don't need to 'write a wrapper for calling compiled code'. You >just >> >call it. >> >> Are you really familiar with Managed C++? I'm not, but Microsoft seems >> to have a different ideas about it than you do: >> http://msdn.microsoft.com/vstudio/nextgen/technology/managedext.asp > >Just because they mention the word 'wrapper' in the context of MC++ means >little. It means that you have to explicitly write something for each compiled class and function that you want to use. That is an important point of similarity with calling C++ from other interpreted languages, and it's something that you explicitly denied and claimed as an advantage for Managed C++. > [..] use managed extensions to write thin, high-performance wrappers > that make your C++ code callable from .NET components. > >and > > The wrapper class acts as a mapping layer between the managed class and >the unmanaged C++ class. > >Fairynuff. All this says is that you must use a .NET CLR language in there >somewhere if you wish to use .NET CLR. We were talking about access to non .NET stuff from .NET One of the main reasons to use something like C++ in the first place is its performance as non .NET stuff. If one isn't interested in that, I don't think it is the right language choice. >If you are staying within the CLR howerver (for instance, calling MC++ from >Python, or building a VisualBasic class hierarchy using a mixture of MC++ >and Perl classes), then you do not need to 'wrap' anything. From Python, if >you want to call a method defined in VisualBasic, you just call it. From >REXX, if you want to create an object that is defined in MC++, you just do >so. No wrapping required. Which is interesting, probably much more complicated and subtle in practice, than you (and Microsoft?) claim, but also beside the point. >> I know quite a bit about templates and template 'meta-programming'. >> That's why I mentioned templates in response to your original claim >> that C++ provides good support for metaprogramming. It doesn't. >> >> The book _Generative Programming: Methods, Tools, and Applications_ >> by Czarnecki and and Eisenecker has some especially amusing chapters >> on the theoretical Turing completeness template meta-programs. > >Sorry, I had some trouble understanding the end of this sentence. They show how to build things like conditionals and looping constructs out of template type instantiations operations and parameterized typedefs, which theoretically allows one to arbitrarily manipulate class definitions within the compile time instantiation process itself (assuming idealizations like unbounded definitional recursion, etc.) >> But from a practical point of view, these techniques are mostly >> amusing tricks. > >You obviously haven't used meta-programming techniques practically then. I was talking about the techniques in the book in a somewhat tongue and cheek way. The point being that one doesn't want to write programs in this awkward meta language to create real programs unless one has to. It is much nicer to work with a language like Ruby or Common Lisp that is designed to do powerful manipulations on text and can then execute the results. >They don't address most of the real world >> meta-problems that a programmer might face and they don't >> transcend the need to be able to define the executable >> routines of interest at compile time, before interacting >> with the user and their specific input and data. >Um, what is a 'meta-problem'? Writing a piece of code using a parameterized 'specification' of some type, that will solve an object language problem. >Surely there are just problems. Is the problem fully specified at compile time? If it's not, then it probably has to be solved in different way in a static language like C++. >Maybe we are >talking about different things. By "meta-programming" I mean a set of >techniques that allow the programmer to define and build-up types and type >systems programmatically. What you describe sounds like choosing a DLL to >load. That isn't called "meta-programming", that's called "loading a DLL". >I have also heard the term 'meta-programming' used in a different context, >namely the study of program structure and some parsing systems. But when I >refer to "meta-programming", I am explicitly refering to the former >definition. For instance I find the following types as important as anything >else in my toolbox: > >template <int Test, typename A, typename B> >struct IF { typedef A Result; } > >template <typename A, typename B> >struct IF<0, A, B> { typedef B Result; } > >template <class Ty> >struct is_void { enum { Result = false; } }; > >template <> >struct is_void<void> { enum { Result = true; } }; > >template <class Ty> >struct Storage { > typedef IF<is_void<Ty>::Result, char, Ty>::Result StorageType; >private: > StorageType storage; }; > >Storage<void> foo; >Storage<string> bar; Yes, this is the type of technique that Czarnecki et al. discuss. And once again, my point is that all of your parameters that are used to build these structures need to be defined at compile time, and also this meta-language is very awkward to work with - it can't take strings or floats as first-class parameters, for example. >> ordinary function object technique is a big improvement >> on C, in this regard, but still quite limited compared >> to the techniques offered by an interpreted language >> with closures, etc. > >Many meta techniques are meaningless outside of a strong statically typed >system. Or perhaps that is true only as far as my understanding of meta >programming. Perhaps you could give some examples of meta programming in >Ruby or another interpreted language? There are many routines for taking strings and interpreting them as excutable code or insructions for modifying existing code. These include the methods instance_eval and send of class Object and eval and proc of the module Kernel, but there are many others. Any routine for creating appropriate strings can be used with these methods to do meta-programming. This is so straightforward in a language like Ruby that mostly nobody bothers to name it as such. It is taken for granted. There are also lots of methods for getting string representations of existing objects and methods that can then be embedded in other string constructions. >Post script. Perhaps you mean generating program source code from a program? >That would qualify as 'meta-programming' as well, although it would seem a >less elegant solution (if only because it requires two stages). In Ruby and other dynamic languages, there are not separate stages. In C++, if one wants to use the full power of the C++ language to do the meta-programming, then it would be a separate stage and it would involve a system call to a compiler, which is not part of the language. Otherwise, one must work with unexpressive template meta language. -= Josh