tag:blogger.com,1999:blog-6325352779084372042024-03-14T02:43:35.484-07:00Programming: To the LimitA blog about in-depth analysis and understanding of programming, with a focus on C++.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-632535277908437204.post-14292097962202320492009-07-21T19:40:00.000-07:002009-07-21T20:13:17.798-07:00Concepts, C++0x, and the LimitBy now, I'm sure you have heard the news. The C++ Working Group has decided to remove Concepts from the C++0x specification. The first question you might have is this: what are Concepts?<br /><br />This is pretty simple, and I'll explain by way of analogy. Object Oriented Programming (class hierarchies with virtual functions) and Generic Programming (templates) are the prime language-based C++ mechanisms for allowing old code to call new code. Having new code use old code is easy; you call a function. Having old code call code that has not yet been written is harder.<br /><br />OOP does this by using prototypes, explicit constructors/destructors and function pointers (under the hood, of course). You provide a prototype (your class), explicitly defining which functions can and cannot be changed in derived classes. Under the hood, the compiler creates a small struct for each class that contains the virtual table: the list of function pointers that this class uses. When you derive a new class and override other virtual functions, the struct that your new class uses is created by copying the base class and then overwriting any overridden function pointers.<br /><br />The important part of this is that it is all very <em>explicit</em>. Everything is directly spelled out for both the compiler and the user. B derives from A, so anything that takes a pointer/reference to A can also take B. End of story.<br /><br />Generic programming is very <em>implicit</em>. A templated function imposes some requirement on the type of the object that it uses. However, that requirement is <em>never</em> spelled out anywhere. It is defined entirely based on how that template function, and any template functions it calls, uses the type. This interface doesn't even have to be on the type itself; a template can do odd things like require that there be a free function that will take this type as a parameter. If the type you pass in has the appropriate interface, then everyone's happy. If it doesn't, you get a compiler error.<br /><br />Now, the problem with this is that compiler error. Somewhere deep in the bowels of some template function, something tries to make a call or perform an operation that the type can't handle. That, according to C++, is where the error happened. The compiler now must unroll the call hierarchy, listing each and every function, template type, and so forth along the way, until they reach the cite where the error really happened: the place where you instantiated the template.<br /><br />Also, the error message itself is usually not something as clear as "the type X you used in template Y needs operation Z that is not available on that type." It is usually obtuse and involves a lot of text about innumerable template types and expansions. It even exposes some of the implementation details of the template you may be using.<br /><br />Concepts are a proposed way to create a functioning, <em>explicit</em> interface for template parameters. If you're using a template that has a Concept, attempting to use a type that does not conform to the Concept will cause an immediate compiler error, with a reasonable error message explaining that the type doesn't conform to the Concept. It also helps in writing templates. Before, you could do anything with a template parameter and the code had to assume it'd work until someone tried to instantiate it. If a parameter has a Concept constraint on it, then attempting to perform an operation not listed in that Concept will provoke a compile error in the template itself.<br /><br />All in all, it sounds like a great contract idea. And it had been built up as one of the major selling features of C++0x.<br /><br />So why'd they ditch it?<br /><br />Well, first of all, it just wasn't maturing. ConceptGCC, an implementation of some of the older forms of the various Concepts proposals, stopped being developed. The C++ working group has no resources to spend on keeping this thing fairly up and running.<br /><br />The Standard Library was also becoming a problem with Concepts. Obviously, the library would have been Conceptualized, but there was no clear idea on how to do that. And without a functioning implementation, all the C++ WG could do was argue about one way vs. another.<br /><br />And all of this non-advancement started mucking up C++0x's schedule. The 0x is supposed to mean pre-2010. Faced with the possibility of C++0x being dramatically delaid (numbers like 2012-2013 were being thrown around), the WG decided to chuck the dead-weight and leave Concepts for the next standard.<br /><br />Was this the right choice?<br /><br /><em>Absolutely!</em> And here's why.<br /><br />Despite all of the hype around Concepts, we are talking about a feature that exists <em>primarily</em> to make error messages nicer. The Concepts proposal does have some interesting adaptation features, that allows one to write a mapping object from an explicit type to a Concept. This object would be used, thus allowing you to make something that doesn't entirely conform to a Concept to do so. But even that isn't such a huge feature, as you can write wrapper classes to get similar functionality (though you must then explicitly use them).<br /><br />For me, it comes down to day-to-day utility. Concepts won't make my code faster; r-value references will. Concepts won't make using standard algorithms that much easier; lambdas will. Concepts won't decrease the number of times I have to type out a typename; "auto" (like "var" in C#) will. And so on.<br /><br />C++0x is a <em>lot</em> more than just Concepts. C++0x has productivity enhancements (auto, lambda), performance enhancements (r-value references), and just flat out cool stuff (uniform initialization, user-defined literals). Delaying all of that stuff just to get nicer error messages for template misuse would have been a crime.<br /><br />I wish C++0x could have had Concepts in it. But getting the rest of the stuff out to the public is far, <em>far</em> more important.<br /><br />A tip of the hat to the C++ Working Group on sacrificing one of their sacred cows for the betterment of the rest. We'll see Concepts come back for the next standard.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-53524998352893242982008-09-04T13:46:00.000-07:002008-09-04T14:40:35.262-07:00Modular Programming and the Push ModelThus far, we've talked often about the low-level details of code. We've basically been operating on the function level and what goes inside them. This article will thus be the first to deal with the entire structure of code.<br /><br />I practice what I (and probably others) call "Modular" programming. That is, when working on a project of any real size, the project is broken down into a set of discrete modules (built as C++ static libraries). Each module represents code that does a single, specific thing. That is the most important aspect of module design: modules should be as focused and minimal as reasonable.<br /><br />Note that it is "as reasonable," not "as possible." And there is a good reason for this. The more modules you have, the harder it is to find a problem. Bugs can be local to a module, or they can arise through interactions between modules. The more modules you have, the more interactions you have to debug through. So there is tension between having specific modules and ease of debugging.<br /><br />Keeping modules minimal is key to making this work. One of the primary benefits of modular programming is code reuse: if you code is broken down into discrete, atomic bits, it is much easier to use later. The bigger and more complicated the module, the less likely that it will be a good fit for your later needs.<br /><br />One big problem with modules is interdependency. There will be modules that depend on the presence of certain other code. In many cases, this is an intrinsic <em>need</em>, but sometimes it is not. The real problem come with telling when a module truly needs another module.<br /><br />The reason this is a problem is that the more dependent modules are on one another, the less likely you are to reuse that module.<br /><br />Let's say you're writing a music player application, ala WinAMP or Foobar. Breaking it up into modules, you need at least the following modules:<br /><il><br /><li>Music playing. Takes a file and plays music, with various controls to stop, get the current time, etc.</li><br /><li>Tag identification. Takes a file and determines the various tag bits in the file.</li><br /><li>Playlist manager. Has a list of files in an order, can re-order them, has one that is "current", etc.</li><br /></il><br /><br />This is hardly comprehensive, but it will do for now. The question is this: does the playlist manager need the tag identifier module? Yes, but only if the playlist manager module includes the code for <em>drawing</em> the playlist. If it instead just a wrapper around a std::vector (or more likely, a std::list) of filenames, no. Some other code will be responsible for drawing the list and processing user input/output: a module who will be dependent on both the playlist manager and the tag identifier. The proper modulaization of this is to make the playlist low-level, and provide a higher level module that understands the GUI module and so forth.<br /><br />If this sounds similar to the old UNIX philosophy of "do one thing, do it well," then you're right. However, this is applied to code rather than executables, since code can more easily communicate with other code than executables with other executables.<br /><br />The fundamental key to all this is what I call the "Push Model". The Push Model describes how modules interface with other modules, as well as how modules internally work. If module B calls any function from module A, then module B is dependent on module A. If module A is dependent on module C, then B is also dependent on C, but indirectly.<br /><br />Also, the Push Model says that the results of a function call should be based only on the function parameters, the state of the class being called, some module-global state, and the module-global state of any module that is directly or indirectly dependent on this module. There are exceptions, of course (resources, input systems, errors, etc), but that's the general rule.<br /><br />The Push Model ensures that a module is truly <em>modular</em>.<br /><br />However, this is all nice in theory. There are always problems. We'll get to that in another article, though.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-43886448661637574712007-12-04T15:17:00.000-08:002009-12-10T16:54:41.953-08:00Interface my CodeOnce upon a time, <a href=http://cpplimitscience.blogspot.com/2006/11/pimp-my-code.html>I talked about Pimpl</a>. Basically, its a way of hiding the implementation details from external code. The primary benefit is improved compile times, since header files do not have to include a bunch of code that nobody cares about, and only the internals of a system need recompiling when external code changes.<br /><br />As the primary example for Pimpl, I used what I described as "entity from a game system". The example brings up a specific problem, one that is not unique to games. That is, of the "fat interface" object, the object that needs to know about everything, everywhere.<br /><br />Here is that example again, pre-Pimpl:<br /><pre><br />class GameEntity<br />{<br />public:<br /> GameEntity();<br /> virtual ~GameEntity();<br /><br />private:<br /> boost::shared_ptr<Render::MeshClass> m_Mesh;<br /> boost::shared_ptr<Anim::AnimSystem> m_AnimationSystem;<br /> std::vector<boost::shared_ptr<Audio::Sounds> > m_SoundList;<br /> std::vector<boost::shared_ptr<Coll::CollisionMesh> > m_CollList;<br /> boost::shared_ptr<Physics::PhysicalObject> m_PhysicsObj;<br />};<br /></pre><br /><br />Now, the Pimpl version does a great job of hiding the internals:<br /><pre><br />class GameEntityImpl;<br /><br />class GameEntity<br />{<br />public:<br /> GameEntity();<br /> virtual ~GameEntity();<br /><br />private:<br /> boost::shared_ptr<GameEntityImpl> m_Impl;<br />};<br /></pre><br /><br />Now, the only #include that the external system needs to do is with boost/shared_ptr. That's all well and good, but there's something missing... the interface. GameEntity isn't terribly useful without its interface. And while we no longer expose numerous classes from the internals, the interface would force us to do so:<br /><pre><br />class GameEntityImpl;<br /><br />class GameEntity<br />{<br />public:<br /> GameEntity();<br /> virtual ~GameEntity();<br /><br /> void EnumerateCollisionVolumes(boost::function<void(boost::shared_ptr<const Physics::CollisionVolume>)>) const;<br /> void EnumerateMeshes(boost::function<void(boost::shared_ptr<const Render::Mesh>)>) const;<br /> boost::shared_ptr<Ai::AiController> GetAI();<br /> boost::shared_ptr<const Ai::AiController> GetAI() const;<br /> void PlayAnimation(boost::shared_ptr<const Anim::Animation> pTheAnim);<br /><br /> void SetPosition(const Position &thePos);<br /> void SetOrientation(const Orientation &theOrientation);<br /><br />private:<br /> boost::shared_ptr<GameEntityImpl> m_Impl;<br />};<br /></pre><br /><br />This is really no better than before. Oh, it still gets rid of certain implementation details, like the use of std::vector and such. But that's all; the user still needs the definition of a lot of classes.<br /><br />Also, there is the problem of having fat interfaces. What I depicted is the tip of the iceberg; it is not uncommon for the core entity classes to have hundreds of member functions.<br /><br />There is a way to solve all of these problems at once. Basically, you use your Pimpl differently.<br /><br />Pimpl has a publicly available interface class, but also a private implementation class. The solution is to, instead of having one public interface class, have many. One for different uses of the class.<br /><br />So, in this case, GameEntity objects would be created through some global function interface. The code that creates a GameEntity needs to know about all the different bits, so you can't avoid that one. But what is created is the private implementation, which is stored by <tt>boost::shared_ptr</tt> in a list accessible by a unique name. It would also create the primary public interface class, called GameEntity, which is returned to the user.<br /><br />GameEntity would have a number of functions that would return different interfaces. So, there would be a physics interface, rendering interface, sound interface, etc. These all expose functions and classes that much of the game code can freely ignore. All of them have <tt>shared_ptr</tt>s back to the private implementation.<br /><br />So, your GameEntity looks like:<br /><pre><br />class GameEntityImpl;<br />class PhysicsEntity;<br />class RenderEntity;<br />class AiEntity;<br />class AnimEntity;<br /><br />class GameEntity<br />{<br />public:<br /> virtual ~GameEntity();<br /><br /> //Interface retrieval<br /> boost::shared_ptr<PhysicsEntity> GetPhysicsEntity();<br /> boost::shared_ptr<const PhysicsEntity> GetPhysicsEntity() const;<br /> boost::shared_ptr<RenderEntity> GetRenderEntity();<br /> boost::shared_ptr<const RenderEntity> GetRenderEntity() const;<br /> boost::shared_ptr<AiEntity> GetAiEntity();<br /> boost::shared_ptr<const AiEntity> GetAiEntity() const;<br /> boost::shared_ptr<AnimEntity> GetAnimEntity();<br /> boost::shared_ptr<const AnimEntity> GetAnimEntity() const;<br /><br /> std::string GetEntityName() const;<br /><br /> void SetPosition(const Position &thePos);<br /> void SetOrientation(const Orientation &theOrientation);<br /><br />private:<br /> GameEntity();<br /><br /> boost::shared_ptr<GameEntityImpl> m_Impl;<br /></pre><br />This works perfectly. It hides everything from prying eyes, while creating interfaces for specific kinds of tasks. Because all of the interfaces point to the same object, they can call any internal code they wish. So the generic GameEntity interface can have expose functions like SetPosition which operate on the physics object (the ultimate source of the position) without having to go to the PhysicsEntity to do so. The PhysicsEntity will expose it of course, but it will also expose other functions.<br /><br />Also, if the necessary objects for a certain kind of interface don't exist for a particular GameEntity, then the interface retrieval function will simply return NULL. It forces the user to check if the GameEntity, for example, has an AI before calling AI function.<br /><br />I call this "Interface-based Programming". The data is perfectly hidden behind specific views into that data, with each view being categorized for specific functions and purposes.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com1tag:blogger.com,1999:blog-632535277908437204.post-50964304418805724802007-09-20T13:54:00.000-07:002007-09-20T13:51:18.024-07:00Parsing, C++ Style. Part 1I'm going to let you in on a secret: I hate rote busywork programming. I can't stand boring, trivial code. Oh, I know it needs to be done, but if I've done it 20 times before, odds are I'm going to find a way to keep from having to do it a 21st time. That's one of the things that's nice about using C++.<br /><br />One task I detest with a passion is writing a parser. We've all had to do it. Load a text file, tokenize it based on some pattern or whatever, look for the data you're interested in, check for errors in formatting, etc. It's easy and boring. And, more importantly, highly error prone.<br /><br />The latter is a real sticking point. The only thing I hate more than writing a praser is having to <em>debug</em> one. Adding to that is the fact that debugging a parser is not like unit testing or something of that nature; it's a totally input driven process. If you forget a particular case, or didn't anticipate something, it will come back to bite you.<br /><br />Fact is, I shouldn't <em>have</em> to parse code manually. I should have some API or library or something that I can apply to a text file and read it. Worst case, I should be able to define the format of the file, run the file through the parser with that format, and get a parse tree representation of the file, or an error if the file is not formatted properly. Best case, instead of a parse tree, my code simply gets called during the act of parsing the file in question.<br /><br />Now, there are two utilities in particular that I personally rely upon for 95% or more of my parsing needs. The first is <a href="http://xmlsoft.org/">LibXML2</a>. It's a C-based library (though there's an unpleasant C++ front end with an obnoxious license available, if you really need it), so it doesn't qualify as C++ Limit Science.<br /><br />So, I lean on XML a lot. However, though XML is a nice language for the person writing the document, it's not particularly nice for the person reading it. Even with LibXML2, you have to do a lot of rote parsing work.<br /><br />For formats that tend to be generated from code rather than by an external user, I prefer a combination of <a href="http://www.lua.org/">Lua</a> and <a href="">Luabind</a>. Lua is a very easy to use scripting language, but the origin of Lua was in configuration languages. As such, Lua makes a handy file format. All you do is have the Lua script store its data as a large table, likely with nesting. Imagine a gigantic arbitrary struct with any data you can imagine. It can be passed around as plain text, but it can also be compiled into Lua bytecode for size purposes. And thanks to Luabind (a C++ library), actually accessing the contents of the object is much easier than with the Lua C API. It is very easy to generate files and it is likewise easy to read them. And if someone wrote the file in a syntactically erroneous way, Lua will simply report an error at compile time.<br /><br />Taken together, they cover most of my parsing needs. XML is used for things the user will modify or create, and Lua is used for most everything else.<br /><br />But then comes the big problem. What do you do when you have no control over the file format?<br /><br />This is more likely than you might think at first glance. HTML and XML may be derived from the same source (SGML), but they are not compatible. And HTML certainly isn't Lua. Or maybe you're trying to write a scripting system yourself. Unless you're going to force your users to script in XML (yuck), you will need to write a parser of some kind. Or maybe you need to be able to parse some simple strings that the user enters, such as for a text adventure or some such.<br /><br />And that's where Boost comes in. Or rather, Boost.Spirit.<br /><br />Spirit is a very large, header-only library, but it's founded on a simple predicate: make text parsing easy. It is designed for low-to-medium scale parsing; high scale parsing, as for a highly grammatically complex language like C++, is at the very far end of Spirit's capabilities. It can do it, but you will certainly not like what it does to your compile times.<br /><br />This is to contrast Spirit with it's primary alternatives, the preprocessing-based Lex/Yacc and Flex/Bison. These alternatives require the user to write a grammar in a special syntax and add specialized preprocessing commands into their build pipeline to generate C files for doing the parsing. They're functional, but rather arcane, requiring external executables and so forth.<br /><br />Spirit, by contrast, leverages a preprocessor that you already have: your <em>C++ template</em> preprocessor. Spirit is a template metaprogramming library that allows the user to define a grammar using a syntax that is not unlike <a href="http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form">Enhanced Backus Naur Form</a>. It also allows the user to provide semantic actions, functions that will be called when a certain parsed element is reached.<br /><br />Higher-level Spirit functions, built on the base functionality described above, allow for the creation of an entire parse tree of the document, defined by special semantic actions. And of course, Spirit has the Phoenix functional programming library in it (which it uses internally), which makes it easier to build semantic actions for various bits of functionality.<br /><br />The core foundation of Spirit isn't really a parser per se: it is a tokenizer and recognizer. It is, in essence, a schema language. It takes a string and a grammar and returns true if the string fits the grammar and false otherwise. Along the way, it will call various user-defined functions on the parsed text if it matches.<br /><br />Here is a very simple example of a Spirit parser:<br /><pre>using boost::spirit;<br /><br />bool RecognizeNumberSequence(const char *strInput)<br /> {<br /> return parse(strInput, real_p >> *(',' >> real_p), space_p).full;<br /> }</pre><br />This will return true if <tt>strInput</tt> is a comma-separated list of real numbers.<br /><br />The second input to the function is a Spirit parser. The expression <tt>real_p >> *(',' >> real_p)</tt> produces a parser object that can be used as input to the <tt>parse</tt> function. The variable <tt>real_p</tt> is a predefined Spirit parser that parses real numbers in all of their various forms.<br /><br />The object <tt>space_p</tt> is a parser recognizing spaces. Used as the third argument to <tt>boost::spirit::parse()</tt>, it represents the "skip parser". This parser tells the parse function how to tokenize the input. That is, what to ignore when parsing. This keeps the main grammar cleaner.<br /><br />Let us break down the main parser expression, "<tt>real_p >> *(',' >> real_p)</tt>". The '>>' operator means that the operand on the left will occur before the one on the right. The '()' means what it seems like; the grouping operator. The '*' operator (C++'s dereference, not multiply) means that the operand will be repeated zero or more times.<br /><br />So, this parser means that there will be a real number, followed by zero or more repetitions of a comma followed by a real number. Basically, a comma-separated list of real numbers. And the <tt>space_p</tt> skip parser means that spaces can occur between any of these elements, but not within a real number.<br /><br />As mentioned, this is not a terribly useful function, as it does not actually do anything with what it parses. It simply detects whether the input is well-formed as stipulated by the two parsers. In the next part, we will deal with actually doing something while parsing.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-16417991876793985622007-09-20T13:15:00.001-07:002007-11-21T15:55:09.866-08:00Cast in GoldCasting. Casts are that dirty little thing that everyone knows not to use but everyone uses it more often than ought to.<br /><br />C introduced us to one kind of cast. You have a thing of type A, and you can try to turn it into a thing of type B. Simple construct for a simple language.<br /><br />C++ created more casts. But there's a funny thing about C++ casts; nobody likes them. Articles have been written about why they should be avoided and why they were a bad idea for the language. Few C++ programmers prefer them over C-style casts.<br /><br />This article will explain what these C++-style casts are and why you should use them a lot more often that you probably do.<br /><br />All of these casts share a common syntax. It reads like, <tt>cast_name<TypeToConvertTo>(expressionToCast);</tt> No matter how small "cast_name" is, it will always be bigger than the nothing that C-style casts use. C++-style casts draw attention to themselves by being large and ugly.<br /><br />This was supposedly done intensionally as a way to discourage their use. Unfortunately, it worked; that's why most everybody just uses C-style casts. The idea was that it would discourage the use of casting in general, but that was madness.<br /><br />There are 4 kinds of C++ casts. There is the <tt>static_cast</tt>, <tt>const_cast</tt>, <tt>reinterpret_cast</tt>, and <tt>dynamic_cast</tt>. Each of them is meant to be used under specific circumstances.<br /><br />The easiest two to defend are reinterpret and dynamic. This is because neither of them have a direct analog with C-style casts.<br /><br />If you have a 32-bit float value, and you want to get it's bit-pattern as an unsigned 32-bit integer, in C, you have to do this:<br /><pre>unsigned int32_t iFloatBits = *(unsigned int32_t *)&fValue;</pre><br />Not only is this somewhat obtuse as to what's happening (you're pretending a float-pointer is an integer pointer), it requires that <tt>fValue</tt> have a memory address, since you have to dereference it. This is highly unnecessary; what you're really asking is for the compiler to bring <tt>fValue</tt>'s bits from a float register into an int register. This is very simple and just about every CPU can do it. But in C, you can't actually say it like that.<br /><br />In C++, you have:<br /><pre>unsigned int32_t iFloatBits = reinterpret_cast<unsigned int32_t>(fValue);</pre><br />The only downside is the sheer length of the expression. But it's a lot more obvious what's going on, so long as the reader understands what C++ casts do.<br /><br />As for <tt>dynamic_cast</tt>, there is no C analog because C doesn't have inheritance. The purpose of this operation is to take a pointer to a base class and turn it into a derived class. Now, of course, that particular base class instance may not actually be that particular derived class. So a regular C-style cast operation is right out, since they are compile-time operations.<br /><br />See, <tt>dynamic_cast</tt> isn't a cast at all really; it's a <em>function call</em>. One that can <em>fail</em>. That is, a particular cast can return NULL if the cast operation cannot work on the specific instance. A dynamic cast is what allows some degree of runtime-type identification. You use it when you need to break the OOP contract and consider a base class to be a derived class.<br /><br />So, it is obvious that both of these are superior to their C analogs (and one doesn't even have a C analog, so it is <em>a priori</em> superior to nothing). However, what of the other two?<br /><br />Well, the main advantage of using <tt>const_cast</tt> is just error checking. A const cast can only add or remove const-ness from a type. As such, you cannot accidentally convert the type to something else by entering the wrong type. This is useful.<br /><br />Also, removing const-ness (which is 99.9% of all <tt>const_cast</tt> uses, since adding const-ness is implicit) is rather rare. It usually happens when interfacing with code that you did not write. Indeed, doing this kind of cast suggests a design flaw or that something ought to be made <tt>mutable</tt>. Outside of that, the times when this kind of cast is truly needed are few indeed. So the larger size of the conversion expression is not a substantial problem.<br /><br />Which brings us to <tt>static_cast</tt>. This is the cast that I can recommend the least. It gives protection from accidentally doing something that reinterpret or const casts should be used for, but that's about it. And so long as we assume that the programmer is intelligent, and therefore is not going to arbitrarily be doing these kinds of conversions, then we should assume that each static cast operation is actually necessary. And if the programmer actually is not intelligent, the ugliness of <tt>static_cast</tt> will not be a deterrent, since they can always use C-style casts anyway.<br /><br />So, either way, it generally better to use C-style casts when you might use a <tt>static_cast</tt>.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-40956189063555947882007-09-12T19:00:00.000-07:002007-09-12T19:07:17.095-07:00One RAII to Rule Them AllRAII: Resource Acquisition Is Initialization.<br /><br />Perhaps the most useless acronym ever.<br /><br />Why? Because it only tells you <em>half</em> of what it is. Perhaps even less.<br /><br />The part of RAII that is in the name is the concept of wrapping all resources in objects. Specifically, the constructor of objects.<br /><br />What the name misses is the basic construct of RAII.<br /><br />Consider the following code:<br /><pre>char *LoadAndProcessData(const char *strFilename)<br />{<br />FILE *pFile = fopen(strFilename, "rb");<br />if(!pFile)<br />return NULL;<br /><br />char *pFileData = new char[50];<br /><br />fread(pFileData, 50, pFile);<br />fclose(pFile);<br /><br />ProcessData(pFileData);<br /><br />return pFileData;<br />}<br /></pre><br />The points of failure in that code are legion. 'fopen' could fail, returning NULL. 'fread' could fail, returning NULL. Even 'new' could fail, either returning NULL or doing everybody's favorite: throwing an exception.<br /><br />The first point, the function handles. Presumably, the calling function will look at the return value, check for NULL, and if it sees NULL, then it will do something useful.<br /><br />The second point, however, gives rise to an unhandled error. If 'fread' fails, the function 'ProcessData' will get uninitialized (or partially initialized) memory. It may fail, throw an exception, or silently succeed but have bad data. None of these are good answers.<br /><br />If 'new' fails, throwing an exception means that we fail. Granted, 'new' will only throw if we are actually out of memory, which isn't a terribly recoverable error. But if it does throw, we will immediately leave the function, without calling 'fclose'. That's bad.<br /><br />File handles from a process tend to be cleaned up OK by the OS, mainly because so many programs are bad about doing it themselves. But it could have been a global resource, like a piece of memory to be shared between two processes (say, the clipboard). Throwing an exception would keep us from properly filling that memory out. Or closing the handle correctly, resulting in a leak. And so on.<br /><br />It is precisely here where C-in-C++ programmers give up on exceptions entirely. After all, if 'new' didn't throw, we wouldn't have a problem.<br /><br />However, there is a much more useful solution to this, one that doesn't turn its back on useful language features. The reasoning behind wanting to preserve exceptions has <a href="http://cpplimitscience.blogspot.com/2007/07/errors-exceptions-and-limit-science.html">been discussed.</a> What we will focus on is the technique that allows us to avoid abandoning exceptions. As well as giving us so much in return.<br /><br />The reason that the acronym RAII is wrongheaded is that it isn't really the resource acquisition that's the issue; it's controlling when the resource is <em>released</em>. After all, 'fopen' does it's job; it creates a file handle well enough. The problem has always been that 'fclose' isn't guaranteed to be called.<br /><br />The C++ specification dictates that, when an exception is caught, the stack will be unwound. All stack variables will have their destructor called, and it will be called in the proper order. Since this coincides with the exact moment we want to destroy the file handle, it makes sense to put the file handle on the stack.<br /><br />RAII principles are as follows:<br /><ol><li>Constructors are required to do actual work. Any and all things that could be deemed resource acquisition will only be done in object constructors.</li><li>Any and all resource releasing will be done in object destructors.</li><li>RAII-style objects must have appropriate copy constructors and copy assignment operators, if the object is copyable. If it is not, then it should forcibly be made non-copyable (by deriving from boost::non_copyable, for example).<br /></li><li>If there is a resource that cannot be created directly by a constructor, it must be created and immediately stored in an object with a destructor that will release the resource properly.<br /></li></ol>A few simple rules create a fundamentally different coding style.<br /><br />What qualifies as "resource acquisition"? At a bare minimum, a resource is something you need to have cleaned up. Hence the backwards acronym; we define resources by wanting to get rid of them, not by how we acquire them.<br /><br />Immediately, it becomes obvious that the value returned by operator 'new' qualifies. After all, memory is most definitely something we need to have cleaned up. So as per rule #4, the results of 'new' under RAII programming style must be store din something that will guaranteably call 'delete' when it is finished. We have already seen such an object: <a href="http://cpplimitscience.blogspot.com/2006/11/pointers-to-intelligence.html">boost::shared_ptr</a>. Shared pointers are reference counted, which doesn't qualify in terms of the guarantee, since circular references will prevent the resource from being collected. But they're close enough. There are also std::auto_ptr's and a few others.<br /><br />So dynamically allocated memory is a resource. Files are resources. The GUI system windows, drawing tools, etc, are resources. And so on.<br /><br />However, RAII is actually quite viral. Unless your entire codebase operates under RAII principles (or the non-RAII portions exist in isolated chunks at the bottom of the stack. Leaf-code), exceptions cannot be entirely safe. For our simple example of file openning, we can easily make it perfectly safe by creating a File object that acts as a RAII wrapper over the C FILE handle. The constructor opens the file, throwing an exception on failure, and the destructor closes it. For the simple case, it works just fine.<br /><br />However, if you use that object in a non-RAII fashion (allocate it dynamically and store a pointer on the stack), you lose the guarantee. Which means that your entire codebase must hold everything allocated in a RAII fashion to be perfectly safe in throwing exceptions.<br /><br />There is an implicit 5th rule as well. Because constructors are the only place where resource acquisition is to happen, they also must throw exceptions if the acquisition fails. That is the only way to signal the non-creation of an object. Generally, releasing a resource can't provoke a failure, so it is not much of an issue.<br /><br />This is generally where the C-in-C++ programmers who stuck around decide to leave, as it requires a new coding style.<br /><br />What gets lost are the benefits. After all, if you're being forced to use shared_ptr everywhere, memory leaks will be a lot less likely. Circular references may happen, but that is what weak_ptr is for. Your code will generally be very difficult to break from a resource perspective.<br /><br />Also, exceptions are a very useful piece of functionality. They can be used as a complex piece of flow control (but only sparingly, and only when it really matters). And, as mentioned earlier, they have a vital role in reporting certain kinds of errors.<br /><br />In general, it is a more rigid programming style, requiring, particularly for shared_ptr relationships, a degree of forethought in the design phase. But it can save a lot of time dealing with errors, memory leaks, and other concerns.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-5646365486974598252007-07-22T20:11:00.000-07:002007-11-21T15:49:09.749-08:00Errors, Exceptions, and Limit ScienceAs it currently stands, there are basically two kinds of C++ programmers. The distinctions can be more subtle than those I'm about to describe, but it works well enough for these purposes.<br /><br />First, there are the C++ programmers who pretend that C++ is really just C with classes. They're wary of any form of templates, RAII, and so forth. And exception handling is right out for these people. They solve problems as a programmer would with C, though they may dabble in some C++-isms. The STL is looked on with a wary eye, if for no other reason than that it does not do things the C way.<br /><br />The other kind of C++ programmer are those more like myself. They see C++ as a fundamentally different beast from C. They solve problems in C++ by using C++ wherever reasonable. They tend to avoid C-isms like function pointers. Some of these people overindulge in certain aspects of C++, but in general, they're trying to use the language as it is meant to be used rather than merely taking the most obviously useful features and ignoring the rest.<br /><br />And nowhere is the difference more clear than in the way that they deal with erroneous conditions. The C-in-C++ style programmer has only two real tools to handle error conditions: call <tt>exit()</tt> or some other form of immediate program termination (asserts, etc), or return an error code and let the user handle it.<br /><br />Quick side note. The reason the C-in-C++ programmer refuses to use exceptions tends to be because they abhor RAII. You can't really use one without the other; you can't feel safe about letting exceptions unwind the stack unless you can guarantee that everything will get cleaned up. And you can't do that without embracing RAII fully. And then, if you're not throwing exceptions, you can't really use RAII, because exceptions are the only way to signal a constructor error. Thus it is a vicious circle; one must have either both or neither. "Do, or do not; there is no try."<br /><br />In any case, the programmer who embraces C++ has more than just two options. Which is fortunate, as there are multiple different kinds of errors, and many C-style C++ doesn't recognize.<br /><br />The first kind of error is the most obvious. Some piece of code has detected a condition so horrific that it feels that the program simply cannot continue. It must die, and do so immediately. It does not consult other code, and nobody has any way of preventing this. C handles this through <tt>exit()</tt>, but the C++ way is through <tt>std::terminate</tt>. In either case, they both mean the same thing: the program must die right now.<br /><br />Of course, C++ didn't add <tt>std::terminate</tt> just because. You can actually set up a generic termination function that will be called by std::terminate. Now, this code really ought not throw any exceptions (or do things like allocate memory that might throw), because that's really bad inside of <tt>terminate</tt>. But outside of that, everything else is pretty much OK.<br /><br />These kinds of errors are the kind you don't expect to get, but which may happen in the course of development. Asserts are another common way of dealing with them.<br /><br />Next up is an error that is considered recoverable by the code that detects the error. What constitutes "recoverable" differs even from person to person (personally, I think throwing in the event of an out-of-memory error is absolutely wrong. The program should die immediately if not sooner). But in general, it is something that the code thinks that the calling code should be informed of.<br /><br />C-style C++ has only one way of doing this: an error code. A return value from a function that the user code then detects and acts on.<br /><br />There are basically two types of error codes: the kind that the calling code is supposed to ignore and the kind that it isn't. This corresponds to two basic subtypes of the recoverable error: "recover or die" and "recover or live".<br /><br />What I mean by "recover or die" is that the calling code should either detect the error or the program's execution should halt. That is, the error, while being recoverable, requires action on the user's part. The error cannot be recovered from by pretending it didn't happen; someone external to the code must <em>do</em> something.<br /><br />"Recover or live" is the opposite. It's OK if the user does not detect that the error happened. Everything is considered in a good enough state that the program can continue operating as normal. If the programmer wants to detect the error and do something, fine, but the program can continue as normal.<br /><br />One big question a programmer has to decide when detecting a recoverable error is which kind it is. If you're writing a file, is it a recover-or-die or recover-or-live error? Technically, it could be the latter, but would a programmer appreciate that?<br /><br />In any case, C-style C++ doesn't give the programmer the ability to handle "recover or die". After all, you can completely ignore any return value you wish, so error codes are meaningful only if the programmer using the code chooses to make them meaningful. The lower-level programmer has no way of <em>forcing</em> the higher-level code to handle the error.<br /><br />In C++, exceptions provide a way to require testing the error code. However, there's another interesting way to force error testing that doesn't require some of the verbosity of exceptions. Exceptions allow any code in the callstack to handle the exception. The alternative method must be handled immediately at the call site. However, it does force the user to handle it, unlike error codes.<br /><br />C-style C++ users do use this quite a bit themselves. Many functions that return a meaningful value (say, <tt>GetObjectType(x)</tt>) will return <tt>NULL</tt> in the event of a recoverable error. It is not a "recover-or-live" error, because the program will eventually reference NULL, thus causing death. But of course, this doesn't work on non-pointer types.<br /><br />Thanks once again to the Boost library, we have <a href="http://www.boost.org/libs/optional/doc/optional.html">Boost.Optional</a>. Basically, a <tt>boost::optional<typename></tt> object has either a (presumably valid) value of the typename or nothing. In order to use the optional value, the user must call a <tt>get</tt> function, which will assert in debug builds and do other unpleasant things in release builds. In either case, the user of the code is forced to at least think about the fact that the function may return nothing, since they have to store the <tt>boost::optional</tt> return value.<br /><br />It is a weaker form than exceptions, but it is better and much less verbose in many cases. Particularly so if it is semantically OK for it to return nothing.<br /><br />Real C++ style still can use errorcodes for "recover or live" errors. But it is good that C++ has ways of forcing the user to handle errors or the program will crash.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com2tag:blogger.com,1999:blog-632535277908437204.post-35430329204078316562007-01-11T11:43:00.000-08:002007-03-30T17:43:55.052-07:00Functional Programming in C++ 3I'm skipping part 2, because I'm having some difficulty coming up with a really good example of why you <em>need</em> functional programming. Oh, sometimes it's nice, but I've yet to see a point where it's necessary.<br /><br />We've actually had a slight introduction to functional programming, or some aspects of it before. The article <a href="http://cpplimitscience.blogspot.com/2006/11/making-algorithms-work-for-you.html">involving</a> Boost::Bind, for example. At the end, I mention the ability to compose bound functions to create new ones. And Boost::Bind has the ability to convert the parameters of a functor from one to another.<br /><br />Of course, that's not nearly good enough for real functional programming.<br /><br />In terms of getting this done in C++, there are several options. <a href="http:\\www.boost.org">Boost</a> (the fount from which all good things flow), of course, has a library called <a href="http://www.boost.org/doc/html/lambda.html">Lambda</a>. This allows you to generate functions of the form:<br /><pre>cout << (1 + _1)</pre><br />This creates a function object inline. This function object takes one parameter, adds one to it, and prints it to standard out.<br /><br />However, Boost::Lambda has a number of limitations. Chief among them, having only 3 arguments, which can be quite limiting. Also, it replicates Boost::Bind (and is incompatible with Boost::Bind), but replicates it without the powerful Boost:MemFn functionality, so you can't use member functions in Boost::Lambda.<br /><br />In short, Boost::Lambda doesn't take things to the limit, doesn't give us all of functional programming. So, how do we do it?<br /><br />Within Boost lies the greatness that is <a href="http://www.boost.org/libs/spirit/index.html">Spirit</a>. Spirit is a parser framework; you build parsers with it in a style that seems very similar to <a href="http://en.wikipedia.org/wiki/EBNF">Extended Backus–Naur Form</a>. But that's not why we're talking about Spirit. For within the Spirit slumbers a beast of great power: Spirit::<a href="http://www.boost.org/libs/spirit/phoenix/index.html">Phoenix.</a><br /><br />Phoenix <em>is</em> functional programming. It is Boost::Bind combined with Boost::Lambda, mixed with stuff that you never expected to see in C++. Behold:<br /><pre><br />for_each(c.begin(), c.end(),<br /> if_(arg1 % 2 == 1)<br /> [<br /> cout << arg1 << ' '<br /> ]<br /> );<br /></pre><br />Yes. That does exactly what it looks like. Yes, that is an 'if' statement. Yes, that 'if' statement is in a place where no 'if' statement ever belongs. And yes, that entire expression generates a function object that is passed to for_each and does what it says it does.<br /><br />So, let's take things slow.<br /><br />Remember back to our discussion of Boost::Bind. It used entities named '_1', '_2', etc to represent the first argument, second argument, etc. Phoenix uses 'arg1', 'arg2', etc. Personally, I prefer Phoenix's style, since it uses something close to a word, and I'm pretty wordy in my naming.<br /><br />Let's start with a basic example:<br /><pre>cout << arg1;</pre><br />This statement does not execute 'cout <<'. It merely creates a functional object of one parameter that outputs that parameter.<br /><br />Note that the functional object created does not know nor care what the type of that object is. As long as the operator << has been overloaded for whatever argument you pass in (and that the overload takes the appropriate type, in this case an output stream object), then you may call this function.<br /><br />This goes back to our discussion in part 1, where we said that a function 'f(x) = log(x)' could only take positive values of X or 0, because the function log(x) is undefined on negative numbers. This is the same thing.<br /><br />Note that there is one thing we cannot do, just as we couldn't do with Boost::Bind: catch this function and store it directly. Oh, 'for_each' can do it, but that's only because 'for_each' is templated on the type of that function object. It can store it because it doesn't need to type out what that type is.<br /><br />The type of 'cout << arg1' is not for the feint of heart. And that doesn't even get into some of the functional programming statement stuff.<br /><br />Then again:<br /><pre><br />boost::function<void (int)> integerOutputer = cout << arg1;<br />integerOutputer(5);<br /></pre><br />Maybe we can ;)<br /><br />Thanks to Boost::<a href="http://www.boost.org/doc/html/function.html">Function</a>, we can capture one of these lazy functions and store it. The only limitation is that, because C++ is strongly typed, we can only capture it in a strongly typed object. So we loose a lot of the type genericness that we would normally have with lazy functions.<br /><br />A minor limitation, but one we can accept. Especially since most of the time you're wanting to capture it (for say, a registered callback), you can easily tie down a specific argument list.<br /><br />Another thing we can do is get local variables involved:<br /><pre><br />int iSomeValue;<br />for_each(someVector.begin(), someVector.end(), cout << (variable(iSomeValue) + arg1));<br /></pre><br />This will create a reference to iSomeValue, store it in the functional object, and use it on each envocation. If you have a list, and wish to take the summation of that list:<br /><pre><br />int iSomeValue;<br />for_each(someVector.begin(), someVector.end(), variable(iSomeValue) += arg1);<br /></pre><br />Much easier, and much more intuitive, than making a functor call.<br /><br />It's important to note that 'variable(iSomeValue)' itself is, much like 'arg1', a functional object. So, you could execute, 'variable(iSomeValue)()', if you like really convoluted ways of getting the value of something.<br /><br />Though I haven't discussed Boost::<a href="http://www.boost.org/doc/html/signals.html">Signal</a>, it is one of the chief places where you're going to want to use functional programming, aside from std::algorithms. There is a big difference, though: std::algorithms will immediately use your functional object and then destroy it. Signals, pretty much by definition, will call it whenever it feels like.<br /><br />That's bad when you use 'variable(iSomeValue)'. That's because this variable will not <em>exist</em> by the time the Signal calls it. Remember: the variable() function stores a reference to the variable. And likewise remember that references to stack variables can be hugely dangerous if someone stores them and uses them outside of your scope.<br /><br />Just FYI.<br /><br />To get a bit more formal about things, what 'cout << arg1' is, in Phoenix parlance, is a "lazy function". This means that it is only evaluated when it's arguments are called. However, it is important to note that anything that is a Phoenix lazy function can also have certain things done to it. Like this:<br /><pre>(cout << arg1)(arg2, arg1)</pre><br />This creates a new lazy function. This new lazy function takes two arguments. But the original one only took one.<br /><br />Fortunately, Phoenix doesn't care. What this will do is create a lazy function can can only be evaluated to produce an answer if it is given two (or more) parameters. Because of how this function was constructed, the first argument will be discarded, and the second will be sent to standard out.<br /><br />This becomes very interesting when you start using non-lazy functions as lazy function. AKA, when you start doing Boost::Bind-like stuff:<br /><pre>bind(&SomeFunc)</pre><br />This returns a lazy function. It takes the arguments that the function, functor, or member function took. However, that may not be what you want, especially if that is a member function.<br /><br />Just like with Boost::Bind, the first argument to a member function is the 'this' pointer. If 'this' isn't going to be an argument you expect the caller to use, you need to add it yourself:<br /><pre>bind(&TheClass::SomeFunc2)(*this, arg1, arg2)</pre><br />Notice that it takes a reference to the class rather than a pointer. This means that using a smart pointer is impossible, so you need to make sure that your code makes it impossible for this code to be called beyond the lifetime of this object. Fortunately, Phoenix version 2 will allow the use of references, pointers, or smart pointers.<br /><br />Because Phoenix is a lot more powerful than Boost::Bind, it can do some of the things that we only wished Bind could do:<br /><pre><br />bind(&TheClass::SomeFunc2)(*this, arg1, arg2 + bind(&TheClass::SomeFunc3)(*this, arg3));<br /></pre><br />Which creates a functor that takes 3 arguments and does functional composition. Even modifying the return value of the call to SomeFunc3 before passing it to SomeFunc2. You can do all kinds of nifty stuff with this.<br /><br />The farthest limit of Phoenix however, comes from so-called 'lazy statements'. I scared you with this at the beginning:<br /><pre><br />for_each(c.begin(), c.end(),<br /> if_(arg1 % 2 == 1)<br /> [<br /> cout << arg1 << ' '<br /> ]<br /> );<br /></pre><br />The 'if_' construct is a lazy statement that evaluates it's contents (within the square brackets) only if the condition is true. Just like a regular 'if' statement.<br /><br />Except that, since it's functional programming, it creates a function object that does this. And 'if_' is just the tip of the iceberg. Just about every C++ flow control construct exists as a lazy statement (except goto. But we don't use that anyway). Blocks of code can be multi-line, through the use of comma-separated elements:<br /><pre><br /> if_(arg1 % 2 == 1)<br /> [<br /> cout << arg1 << ' ',<br /> cout << (arg1 + 5) << endl //Note: no comma on the last line.<br /> ]<br /></pre><br />This is incredibly powerful.<br /><br />However, it's important not to go thinking you can just write anything as a lazy statement. For performance reasons (or potential ones; these constructs have not been deeply profiled), it's generally a good idea to use lazy statements for rapid development, then factor them out into real functions that get called. The thing I like about them is that you can use std::for_each() and make it look like a regular for() statement.<br /><br />This article is getting long, so I'll punt on closures. They're not the most important or interesting part of Phoenix anyway.<br /><br />In any case, what you've seen here is merely the beginning. Through Boost::Function and Phoenix, you can have serious functional programming. You can create unnamed functions, compose functions, pull functions from standard C++ functions, and even build functions in a pseudo-C++ language.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com1tag:blogger.com,1999:blog-632535277908437204.post-11760066991480199942006-11-21T20:26:00.000-08:002007-01-10T23:44:55.327-08:00Pimp my CodeC++, as a language, has a number of problems. Perhaps the biggest is the fact that, before you can really talk about an object, function, or other construct, you need to #include it. Java and C# don't impose the same requirement, and few more modern languages do.<br /><br />Of course, C++ is compile-time linked too, unlike most other modern languages.<br /><br />In any case, this poses a problem for a reason. Standard programming practice teaches <em>encapsulation</em>. That is, keeping an object's privates out of the light of day. The problem comes from something like this:<br /><pre><br />class BigBoy<br />{<br />public:<br /> BigBoy();<br /> virtual ~BigBoy();<br /><br /> void DrawBigBoy();<br /><br />private:<br /> boost::shared_ptr<Render::MeshClass> m_Mesh;<br /> boost::shared_ptr<Anim::AnimSystem> m_AnimationSystem;<br /> std::vector<boost::shared_ptr<Audio::Sounds> > m_SoundList;<br /> std::vector<boost::shared_ptr<Coll::CollisionMesh> > m_CollList;<br /> boost::shared_ptr<Physics::PhysicalObject> m_PhysicsObj;<br />};<br /></pre><br />BigBoy could be an entity class from a game system. It stores references to fundamental objects from <strong>5</strong> systems (and I could reasonably add more. It doesn't have AI yet).<br /><br />If you needed to #include"BigBoy.h", you'd need to include headers from each of those 5 systems first.<br /><br />The first attempt to solve this problem is to provide a forward declaration of the classes in this file. That would work, but only because boost::shared_ptr can work with incomplete types. But, then again, now people using BigBoy.h need to #include"boost/shared_ptr.h". If you're a heavy Boost user, that may be your standard mode of operation. But if you're not?<br /><br />You'd also need to #include<vector>, which once again you may not need in your code. Most std::vector implementations aren't exactly short. Maybe one of those could have been a boost::array (fixed-length arrays that work like std::vector's) or a std::list; this just increases the number of different things you need to include.<br /><br />What's worse is that if you <em>change</em> what BigBoy uses internally, you have to go to every file that uses BigBoy and change it. Kinda annoying, yes?<br /><br />Imagine you have a thousand files using BigBoy (and note: this is <em>not</em> unreasonable for large game projects). Or worse, imagine you're writing the Unreal Engine or something, and you could have dozens or hundreds of users, each with hundreds of files that would need to be changed, just because you wanted to use a std::list or a boost::array.<br /><br />What do we do? We <em>pimp</em> the code:<br /><pre><br />class BigBoyImpl;<br /><br />class BigBoy<br />{<br />public:<br /> BigBoy();<br /> virtual ~BigBoy();<br /><br /> void DrawBigBoy();<br /><br />private:<br /> boost::shared_ptr<BigBoyImpl> m_Impl;<br />};<br /></pre><br />OK, what just happened?<br /><br />Well, ignoring what BigBoyImpl is for the moment, I didn't really solve the problem so much as I reduced it. Since boost::shared_ptr works on incomplete types, this is compilable C++. However, I still require that people include boost::shared_ptr.<br /><br />Tough. Most people using Pimpl (I'll get to what that is in a second) would use a naked BigBoyImpl *. I don't because there are times (constructors throwing exceptions) when a destructor for a class will not be evoked. But destructors for member objects will be. The use of boost::shared_ptr guarantees this. Plus, it provides for the possibility of having multiple BigBoy objects with the same BigBoyImpl object; copy constructors can work.<br /><br />At the very least, I'm always going to use boost::shared_ptr. There's not going to be a sudden change to a more feature-rich pointer object (or if there was, I'd probably still have done the change for the naked-pointer version). We no longer have pressure to not change a facet of the implementation of BigBoy.<br /><br />What we did was we took BigBoy and made it a nothing class. It no longer does <em>anything</em>; it is as empty as boost::shared_ptr. It exists to manage it's contents and provide an appropriate interface to them.<br /><br />Which, if you think about it, is what you want an interface class to do: provide an interface.<br /><br />This allows us to avoid the pain of including a thousand and one headers when we aren't using their contents. We get faster compile times (good, especially since heavy use of Boost can slow them down), less compiler fragility, and overall better stuff.<br /><br />Pimpl stands for, "public interface, private implementation" (don't ask how they got Pimpl out of that...). And Pimpl is what we just did. We took the implementation details out of the header and put them into a new class.<br /><br />So, for the implementer, what we have is, instead of a single .h/.cpp pair, we have two: BigBoy.h, BigBoy.cpp, BigBoyImpl.h, BigBoyImpl.cpp. Except that nobody sees BigBoyImpl.h or .cpp; those live in your system and nobody else needs to know they exist.<br /><br />If the 4 file approach bothers you, you can even put the BigBoyImpl class definition in BigBoy.cpp.<br /><br />Sounds solid: what are the downsides?<br /><br />OOP, for one. OOP's more difficult to work with when you have 2 parallel object hierarchies. Plus, it's much harder for a <em>user</em> to derive anything from the class without needing access to the internals. If you used the 4 file approach, those internals are still available (and the user just signed a contract stating that their code can be broken by changes to the internals). Those internals can still use public/protected/private to hide greater details of the implementation.<br /><br />If you used the 2 file approach, there's not much you can do.<br /><br />BTW, it is entirely possible to do some forms of OOP, particularly if it is just for the user, simply by deriving from the interface class. If one is only really adding functionality to the class (in the BigBoy example, creating a BigBoyWithAI), and all crosstalk can be done with the public interface, everything is fine; it works like regular inheritance.<br /><br />Another possible downside is performance. There's a level of indirection now. Allocating the interface means doing two 'new' operations. In BigBoy's case, allocating a BigBoy even in the original method, could have provoked a number of calls to 'new', so adding one more is not so bad. However, if it were a simpler class with no other dynamic allocation going on, and creating/destroying these objects was commonplace, then there could be a performance penalty.<br /><br />Plus, the level of indirection means that inlining doesn't work. I wouldn't be concerned about this, as modern compilers (or, at least, Microsoft's free ones) can do global inlining and optimization. So as long as you have a good compiler watching your back, you're fine.<br /><br />One other upside to Pimping your code: OOP internally is hidden. Now, people are completely unable to do a dynamic cast or figure out what the <em>real</em> type of the object is. This can be a big benefit, particularly if your internals need to frequently talk to one another.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-81887912747952348502006-11-21T11:37:00.000-08:002007-01-23T20:06:58.788-08:00Are You or Are You Not?OOP: Object Oriented Programming. Basically, it's all about polymorphism, inheritance, and virtual methods overriding base class methods.<br /><br />But there's a problem. Like all new tools, there is a certain class of people who believe that this tool should be used everywhere. These people idolize the tool, believing that the tool holds no wrong and should be used wherever possible. And even some places that it shouldn't be possible.<br /><br />The key to taking C++ to the Limit is not just knowing when to use something; it's knowing when <em>not</em> to.<br /><br />So, we're going to talk about how to properly use OOP. Or, more accurately, why it shouldn't be the default state.<br /><br />First, a clarification. When I say "use OOP", I mean to derive a class from a base class for the purpose of using polymorphism to cause something to happen. Any use of classes (or structs) is not OOP; it doesn't become OOP unless you're using a class hierarchy and taking advantage of polymorphism. A class hierarchy alone isn't enough; that's merely a way of sharing interfaces. It is when you have a class hierarchy and you're using polymorphism to treat the derived class like a regular base class instance that you're truly being polymorphic.<br /><br />Basically, the question when you're designing an object with relationships to other objects is this: is it "is a" or "has a"?<br /><br />"Is a" means exactly what it says: Object B <em>is a</em>n Object A. That is, it is reasonable to take a pointer to Object B and cast it into a pointer to Object A. If this is the kind of relationship you want between them, then you're using OOP.<br /><br />"Has a" is likewise rather self-explanatory: Object B <em>has a</em>n Object A. That is, it stores internally a pointer to Object A. Here, you're not using OOP.<br /><br />However, even with this distinction in relationships, we need to go deeper to get at what the ramifications of either choice are.<br /><br />Using "Is a" nets you some advantages.<br /><ul><br /><li><p>It means that the public interface of Object A (the parent) are immediately usable by users of Object B. Object B also gets to use the protected interface of Object A. Basic inheritance.</p></li><li><p>Second, it gives you polymorphism: the ability to make code that used Object A now use Object B while redefining some of Object A's behavior, all without rewriting that code.</p></li><br /></ul>However, there are limitations that "Is a" gives you.<br /><ul><li><p>Basic inheritance may not really be what you want. Object A may have some public interface that Object B wants, but it may not want all of it. So users of Object B will have extra functions that they can use.</p></li><li><p>Object B has a 1:1 relationship with Object A. That is, there can't be two Object A instances that Object B has a relationship with.</p></li><li><p>If there are implementation details in Object A that are of no value to Object B, then Object B instances will have a lot of dead weight.</p></li><br /></ul><br />Notice something about those limitations? They all happen only <em>when you want to acknowledge that Object B exists!</em> That is, when you're using the derived class <em>explicitly</em>. Whether this was through the use of a cast (static_cast, dynamic_cast, or C-standard cast) or something else, it doesn't matter. The limitations come into play when the derived class needs to be used frequently. As long as the code is treating Object B as through it were Object A, and only talking to it through members, everything pretty much works.<br /><br />The take-home point is this: only use "Is a", only use OOP, when your specific intent is to only (or, at least, most of the time) access the object through the base class interface. If you honestly need to look at an Object B as an Object B in a significant portion of the applicable code, it's probably not a good idea to make Object B an actual Object A.<br /><br />In short, only use OOP for code that explicitly exhibits polymorphism.<br /><br />Why? Well, if you don't, what will happen is that you'll create some object hierarchy. And then you're going to want to work around one of those limitations. So, you're going to do something ugly. Whether it's create a fat interface (bubble up virtual methods to the common base class even when they only matter for a derived classes), or other coding pathology.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-8188719075100803312006-11-15T21:32:00.000-08:002007-01-11T00:00:52.258-08:00Making Algorithms Work for YouI'm not a fan of the STL <a href="http://cppreference.com/cppalgorithm/index.html">algorithms</a>. Here's one of the biggest reasons why.<br /><br />Let's say you've got a class. And you've got a std::vector. Now, you want to iterate over that vector and, say, call a member function of that class. This is what you do under STL:<br /><pre>class CallerFunctor<br />{<br />private:<br /> TheClass *m_pTheClass;<br /><br />public:<br /> CallerFunctor(TheClass *pTheClass) : m_pTheClass(pTheClass) {;}<br /> void operator() (const TheObject *pCurrObject)<br /> {<br /> m_pTheClass->TheFunction(pCurrObject);<br /> }<br />}<br /><br />void TheClass::OperateOnList(const std::vector<TheObject *> &theList)<br />{<br /> std::for_each(theList.begin(), theList.end(), CallerFunctor(this));<br />}<br /></pre><br /><br />This is, in my eyes, incredibly verbose and obtuse code. You have this function object whose sole purpose is to call an object. Writing dozens and dozens of these functors is not a valid method for doing this. I prefer code that makes sense, and doesn't have 2 apparent levels of indirection in order to determine what's going on.<br /><br />The biggest problem is that looking at TheClass::OperateOnList alone isn't enough to know what happens. All you know is that some functor is going to be called on every element; you have no idea what this functor will do without looking at it. And it is not apparent that the functor is going to call the ThisClass member function that it eventually will.<br /><br />I could have named CallerFunctor better, perhaps. But the underlying problem is still there: the structure of the code alone is insufficient to let you know what's going to happen. I prefer more obvious code; code that seems correct by inspection.<br /><br />What we'd really like to do is either remove the need for the functor entirely, or simply transform it into something generic that lets the reader know what the generic functor will do without having to track it down.<br /><br />Enter <a href="http://www.boost.org/">Boost</a>::<a href="http://www.boost.org/libs/bind/bind.html">Bind</a> and Boost::<a href="http://www.boost.org/libs/bind/mem_fn.html">MemFn</a>. Boost::Bind allows you to take a "callable" (function, functor, or member function. Things that can be called) and mess with its parameters. But Boost::MemFn is just what the doctor ordered: it allows you transform a member function into a functor. Basically, it does what CallerFunction does, but generically.<br /><br />So, let's see the original code written in this:<br /><pre>void TheClass::OperateOnList(const std::vector<TheObject *> &theList)<br />{<br /> std::for_each(theList.begin(), theList.end(),<br /> boost::bind(&TheClass::TheFunction, this, _1));<br />}<br /></pre><br />Wait, didn't I say I was going to use boost::mem_fn? So what's with the boost::bind?<br /><br />Well, there's two issues. First, boost::mem_fn is actually used by boost::bind. The above boost::bind statement is the equivalent of:<br /><pre>boost::bind(boost::mem_fn(&TheClass::TheFunction), this, _1);<br /></pre><br />Which brings us to problem #2. The construct, "boost::mem_fn(&TheClass::TheFunction)" returns a functor that takes <strong>two</strong> parameters, not one.<br /><br />The first parameter for anything wrapped in a boost::mem_fn object is the 'this' pointer. That is, a pointer to the object type specified for the member function (note: boost::mem_fn can also take data member pointers and convert them into 1-argument functions that return const references to the member). Makes sense; after all, you can't use a member pointer without the class name.<br /><br />The second parameter to the boost::mem_fn object is, of course, the parameter to be passed to the actual member function. If the member function took several parameters, then it would receive all of them.<br /><br />The reason why we need boost::bind is because the std::for_each algorithm expects the function object to take only one parameter. We therefore needed a way to turn boost::mem_fn's 2 argument functor into a 1 argument functor, one that passes a particular 'this' to all invocations of the functor.<br /><br />Hence the use of boost::bind. The job of boost::bind is to turn callables into functors that take fewer arguments than the original callable. So, let's dissect the statement.<br /><br />The first argument passed to boost::bind is the callable. Simple enough. In our case, it was a boost::mem_fn functor that takes 2 parameters.<br /><br />Following that argument is a list of other arguments. These arguments are all what the user expects to pass in to the callable. Since this is all done through template programming hackery (which thankfully we are not exposed to), if you don't pass enough arguments, the compiler will know and complain appropriately. It'll also do type checking for you when you try to use that functor, so that's all good too.<br /><br />You may have noticed this identifier: '_1'. I never defined it (nor a lot of other things), but it's purpose is crucial. When, in a boost::bind argument list, you use _1, you are telling boost::bind to create a function argument that takes 1 argument. More specifically, you are telling the boost::bind object that the first parameter you give to the functor will be passed in this slot to the embedded callable.<br /><br />Confused? Here's an example, without our member function cruft:<br /><pre>int Adder(int x, int y, int z)<br />{<br /> return x + y + z;<br />}<br /><br />void main()<br />{<br /> boost::bind func1(Adder, 1, 2, 3);<br /> boost::bind func2(Adder, _1, _2, _3);<br /> boost::bind func3(Adder, _1, 5, 10);<br /> boost::bind func4(Adder, _1, _1, _1);<br /> boost::bind func5(Adder, _2, _3, _1);<br />}<br /></pre><br />Important note: This is not real boost::bind C++. The type of a boost::bind function is not readily store-able outside of a template parameter. However, let's pretend that this works as it looks like it would if boost::bind were a C++ type. That said, it is possible to use Boost::<a href="http://www.boost.org/doc/html/function.html">Function</a> if the signature of the method can be predetermined.<br /><br />Well, we create 5 boost::bind function objects. What do they do?<br /><br />The workings of func1 are quite simple. func1 is a functor that takes zero parameters and returns 6. Congratulations; we just made a really complicated way of writing the identifier 6 ;)<br /><br />Those underscores in the func2 constructor aren't mistakes; they're vital. The numbers on them refer to the positions of arguments in the resultant functor. Look at it from the perspective of something you understand:<br /><pre>int CallAdder(int a, int b, int c)<br />{<br /> return Adder(a, b, c);<br />}<br /></pre><br />That is literally what we did with func2. It implements CallAdder as a functor; it takes three parameters and passes them in to Adder, returning whatever Adder does.<br /><br />Well, func3 should be fairly simple. It replaces some of Adder's parameters with constant values, but still allows for one parameter. So, it returns a functor that takes one parameter, and adds 15 to it.<br /><br />It is func4 where confusion can start to set in, but it's really quite simple. It creates a functor that takes 1 parameter (because it only ever uses one argument specifier), and uses that argument for all 3 parameters passed to Adder. Therefore, the result is a functor that multiplies its parameter by 3.<br /><br />func5 shows that you can re-order parameters. It is the equivalent of:<br /><pre>int CallAdder(int a, int b, int c)<br />{<br /> return Adder(b, c, a);<br />}<br /></pre><br />Now, since addition is commutative, this has no effect on the outcome.<br /><br />Back to the original example:<br /><pre>boost::bind(boost::mem_fn(&TheClass::TheFunction), this, _1);<br /></pre><br />This creates a functor of 1 parameter. That parameter is passed as the second argument to the given callable, which is a functor of 2 parameters. The value of 'this' is passed as the first argument to the inner callable.<br /><br />Which is exactly what we need, of course.<br /><br />Now, I am aware that std::mem_fn exists, which technically allows what I originally asked for. But Boost::Bind and Boost::MemFn take this concept to the limit, which is what we're all about ;)<br /><br />However, there's more here than just the niftiness of this use of C++. There are innumerable uses of Boost::Bind and Boost::MemFn outside of STL algorithms. But even within that narrow use, there are useful things that you can do which would be impossible with just std::mem_fn.<br /><br />Our initial example made an interesting assumption: that there existed a function TheClass::TheFunction that took one argument of exactly the type the list consisted of. What if it didn't?<br /><br />Now, we can't do anything if TheFunction doesn't take a parameter of the list's type. So one of the parameters must be of that type. However, we could have a TheFunction like:<br /><pre>void TheClass::TheFunction(int iTheFactor,<br /> const TheObject *pTheObject, bool bStoreObj);<br /></pre><br />This member function is not designed to work with a standard algorithm. But we might want it to.<br /><br />We'd have to use an explicit functor again if we were limited to std::mem_fn. Boost::Bind, however, was made for this stuff:<br /><pre> std::for_each(theList.begin(), theList.end(),<br /> boost::bind(&TheClass::TheFunction, this, 15, _1, false));<br /></pre><br />We know by now what this does. More importantly, it makes those standard algorithms much more useful. They don't make your code ugly anymore, and you aren't restricted to making special functions for them.<br /><br />Now, there is a class of function object that can't be encapsulated in just this. For example, if you have a function that doesn't take the listed object type, but takes something similar to it, what you need is the ability to compose functions. I guess that's too much for boost::bind.<br /><br />Or is it? Attend:<br /><pre> std::for_each(theList.begin(), theList.end(),<br /> boost::bind(&TheClass::TheFunction, this, 15,<br /> boost::bind(MutatorFunc, _1), false));<br /></pre><br />Now, granted, you still have to write the mutator function. But this does exactly what we need. It calls the MutatorFunc with the argument (it could have been a member of TheClass), then passes this as the second argument to TheClass::TheFunction.<br /><br />We still needed to write a one-off function: MutatorFunc. So we reintroduced that need due to the complexity of the issue. However, I'm willing to ignore that minor bit of hypocracy, simply because we solve so many other problems without the need of the mutator. And the mutator doesn't make anything worse than what we had before boost::bind; plus, the mutator can just be a bare function rather than a class that needs a 'this' pointer. So the bloat improved a little, in the worst case.<br /><br />That's good enough for me ;)Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-50786645861164577322006-11-15T16:26:00.000-08:002009-12-10T18:58:55.291-08:00Pointers to IntelligenceMemory management. That's what those Java and C# programmers hang over our heads day in and day out. You can't kill a system on garbage collection, but you can on memory leaks.<br />
<br />
Ignoring the inaccuracy of the last statement, having completely manual memory management does cause its problems with regard to C++. Which is why we're going to show you the tools to achieve perfect, <em>provable</em> memory protection. We're taking memory management to the limit!<br />
<br />
And the path to that limit begins, along with so many other good things in C++, not in the C++ Standard Library (or, not yet), but in the <a href="http://www.boost.org/">Boost</a> libraries. As far as I'm concerned, if you don't have Boost on your harddrive, you're not a C++ programmer. It is the <em>rest</em> of the C++ Standard Library; it's that vital.<br />
<br />
For the purposes of memory management, Boost gives us 2 classes of vital importance. In the <a href="http://www.boost.org/libs/smart_ptr/smart_ptr.htm">Boost::smart_ptr</a> library, I present to you boost::shared_ptr and boost::weak_ptr.<br />
<br />
Boost's shared_ptr class is a fairly simple construct. It's a templated class that takes a pointer to an object in its constructor. It has overloaded the pointer dereference operators (* and ->), so that you can use the shared_ptr as though it were a real pointer to that type. And when the shared_ptr object goes out of scope, the shared_ptr class thoughtfully deletes the object that was passed into its constructor.<br />
<br />
Fairly dry, right? Well, I did miss one feature. You can freely copy this shared_ptr wherever you wish (it has a copy constructor). And, so long as <em>any one</em> remains in existence, so too will the object it points to.<br />
<br />
Just think about that for a second. This sounds suspiciously like garbage collection, yes? Of course it does; that's what it is. It functions exactly like a reference counted garbage collector. With one exception: it always happens immediately when the last reference is removed. And personally, I consider that a feature.<br />
<br />
So, what's the catch? Well, there's two issues, one of them shared with all reference counted deallocators: circular references.<br />
<br />
If object A has a shared pointer to B, and object B has a shared pointer to A, and nobody else has any shared pointers to either, neither one will ever be destroyed (or probably called).<br />
<br />
We'll come back to that in a second, because there's a second issue, one that will bite you sooner or later (probably sooner).<br />
<br />
Go back to that paragraph where I described what a shared_ptr does. What do you suppose this code would do:<br />
<pre>SomeObjectType *pSomeObj = new SomeObjectType();
boost::shared_ptr<SomeObjectType> sp1(pSomeObj);
boost::shared_ptr<SomeObjectType> sp2(pSomeObj);
</pre><br />
Well, this is going to be bad. See, both of these shared_ptr objects think that they <em>own</em> that object, and at some point, both of them will try to delete it. One of them is going to succeed, and the other is going to cause the program to explode, behave erratically, or other such things.<br />
<br />
Basically, you can only ever use the pointer constructor for a shared_ptr <em>once</em>. After that, you can only ever copy shared_ptr's from one place to another. You can create new instances, but only from old instances. For any one object, there can only ever be one evocation of the shared_ptr constructor.<br />
<br />
On the surface, this doesn't sound so bad. But it can cause real problems, especially if you're not aware of it.<br />
<br />
The biggest problem comes from wanting a shared_ptr when you're in the class's constructor. Maybe you want this class to register itself with some external (global) object somewhere, so that others may query it by name. Or other such things. In order to do that, you need to give it a shared_ptr.<br />
<br />
However, most users use shared_ptr's like this:<br />
<pre>shared_ptr<SomeObjType> pThePtr = new SomeObjType;
</pre><br />
If SomeObjType's constructor created a shared_ptr from 'this', we'd be in trouble. Which means that the only way to deal with this is through a paradigm like this:<br />
<pre>new SomeObjType(name); //trusting it to register itself.
shared_ptr<SomeObjType> pThePtr = GlobalRegistrar.GetObject(name);
</pre><br />
This is fool-proof... except that you have to remember to do it. And you lose a bit of performance, in that the registrar object has to do a name search (a quick check for the last-added eliminates this performance loss, of course). If you forget to do this, strange bugs can happen; the best you can hope for is that the program will crash. Worst-case, it keeps running, but becomes unstable.<br />
<br />
The following is also a trap:<br />
<pre>SomeObjectType *pTheObj = otherObject.GetSomeObject();
shared_ptr<SomeObjectType> pThePtr = pTheObj;
</pre><br />
This is an error, as that pointer may have previously been wrapped in a shared_ptr. Therefore, the error isn't in the second statement, but in the <em>first</em>.<br />
<br />
The moment you wrap a pointer in a shared_ptr, you have entered into a binding contract, on penalty of incredibly difficult-to-find bugs, that states that you will <em>never</em> pass a bare pointer to this object to <em>anything</em>. <strong>Ever</strong>. I don't care how tired you get of writing, "shared_ptr<SomeObjectType>"; wrap it in a typedef if you have to (SomeObjectTypePtr, for example). You must never do that.<br />
<br />
Shared pointers are viral, and like any good virus, it must infect everything or nothing. As Yoda said, "Try not. Do. Or Do Not; there is no Try." Which is why the best time to wrap an object in a shared_ptr is immediately upon creation.<br />
<br />
The other problem with shared_ptr's is that of circular references. This one can actually be solved. The key to solving it lies both in Boost and in your own attitude.<br />
<br />
The reason this problem comes up is usually for one reason: you've forgotten what it means to have a shared_ptr. If an object stores a shared_ptr to some other object, you are making a <strong>strong</strong> statement about the relationship between these objects (shared_ptr's are often called "strong pointers" for this reason). You are saying, "Object A <strong>cannot</strong> function in any way, shape, or form without Object B. Object B is an intrinsic part of A, and A would be absolutely, totally meaningless without B."<br />
<br />
When phrased that way, you start to realize that you may be overusing shared_ptr's. For example, if you're writing a game AI, it has a reference to a target. Would it be so bad if that target entity just happen to vanish off the face of the code at some point? Probably not; the AI doesn't need a target in order to function (presumably). If it was about to fire and the target's gone (say, killed by something else), then the AI simply needs to be aware of it and move on to something else.<br />
<br />
Boost, like many garbage-collected systems, has a way to express this concept. We represent this with a "weak pointer": boost::weak_ptr. A weak_ptr lives as a conceptual wrapper to shared_ptr. While shared_ptr implements the dereference operator, you need to call a function on a weak_ptr in order to get a shared_ptr. This is for a very good reason, because, unlike shared_ptr's, weak_ptr's <em>may return nothing.</em><br />
<br />
See, a weak_ptr refers to the shared pointer (or copies thereof) that it was given at construction time. But it does not store a copy of that shared_ptr; it simply knows (via some mechanism best left in the Boost library) that the shared_ptr exists and how to generate one. However, if you have the following:<br />
<pre>weak_ptr<SomeObjectType> aWeakPtr;
{
shared_ptr<SomeObjectType> pThePtr = new SomeObjectType;
aWeakPtr = weak_ptr<SomeObjectType>(pThePtr);
}
shared_ptr<SomeObjectType> pNewPtr = aWeakPtr.lock();
pNewPtr->CallFunc();
</pre><br />
This code will crash, guaranteed. The weak_ptr::lock() function retrieves a shared_ptr to the object held by the weak_ptr. However, if all non-weak references to that object have disappeared since the weak_ptr was created, the weak_ptr::lock() function returns an empty shared_ptr. And, of course, dereferencing an empty shared_ptr returns NULL, which means that the function call will give rise to an error.<br />
<br />
This is good. This is exactly what we want, as it allows us to reserve shared_ptr use for when we really mean it, and just pass around weak_ptr's for when we don't. This should cover 99% of all circular reference cases.<br />
<br />
For the rest... restructure your code. Most code is pretty easy to structure in a tree-like fashion. Each level represents a lower-level of code. In general, siblings in this tree should use weak_ptrs with one another, while parents should have strong_ptrs (or inheritance, where appropriate) to their children. And children should not need to know about their parents at all; that's what makes them children in a code sense.<br />
<br />
FYI: the Boost::smart_ptr library is not thread safe. And there's about a thousand ways for multithreading to screw this whole reference-counting thing all up. So, I would strongly suggest you keep your shared_ptr's in different threads or avoid threading entirely if you use this library. Alternatively, you can hack the library to use a semaphore of some sort.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-81724791049121526582006-11-04T00:20:00.000-08:002006-11-07T11:22:12.736-08:00Functional Programming in C++ 1What is functional programming?<br /><br />The answer to that question is strange. If you've graduated from high school, odds are you've seen functional programming... in <em>math class</em>. As such, I'm going to use that as an analogy to explain what functional programming is.<br /><br />In Math, you learned that a function looks like this:<br /><pre><br />f(x) = x + 4<br /></pre><br />The function <b>f</b> takes a single parameter 'x', and returns the value of x added to 4. Algebra tells us that the function <b>f</b> can legally take any value of x. That is, x can be any number, real or imaginary. And the result of the function <b>f</b> is also any number, real or imaginary.<br /><br />Here's another example of a math function:<br /><pre><br />f(x) = 1 / x<br /></pre><br />Algebra tells us that <b>f</b> can take any number, real or imaginary, <em>except</em> 0. That would make the result of <b>f</b> undefined, as 1/0 is illegal. Therefore, the function cannot take that as an input. Also, the function <b>f</b> can return any output, real or imaginary, <em>except</em> 0.<br /><br />Another example that's even more limited:<br /><pre><br />f(x) = log(x)<br /></pre><br /><b>f</b> can only take positive real numbers or 0 (we'll ignore complex numbers, as the log of a complex number is... wierd). And it will only ever return positive real numbers or 0.<br /><br />Something a bit more complex:<br /><pre><br />f(x, y) = x / y<br /></pre><br />This time, <b>f</b> takes two parameters. The parameter x can be any number, but y must not be 0. And the function can return any number as well.<br /><br />And now for something a bit weird:<br /><pre><br />f() = 3 + 4<br /></pre><br />This is a function that takes no parameters. And it returns only one number: 7.<br /><br />So, what was the point of that? Well, that was functional programming.<br /><br />Not convinced that this could be considered programming of any kind? Well, let's proceed.<br /><br />Let's say we have these functions:<br /><pre><br />f(x) = x * 5<br />g(x, y) = x + (4 * y)<br /></pre><br />Two functions now. I'll skip the input/output analysis and move on to composition. Let's say you want to do this:<br /><pre><br />h(x, y) = g(f(y), x)<br /></pre><br />Well, determining what the function <b>h</b> is is pretty simple:<br /><pre><br />h(x, y) = (y * 5) + (4 * x)<br /></pre><br />See that? We just did functional programming. We took two functions, composed them together, and created a third function.<br /><br />You can do more with functional composition. You can lose parameters:<br /><pre><br />h(x) = f(g(x, x))<br /></pre><br />Add new ones:<br /><pre><br />h(x, y, z) = g(x, y) + f(z)<br /></pre><br />And so on.<br /><br />By now, you're probably kinda annoyed with this math lesson. What does this have to do with programming? Well, it's simple.<br /><br />Forget the fact that what I'm about to write is not legal C/C++.<br /><pre><br />float f(float x)<br />{<br /> return x * 5;<br />}<br />float g(float x, float y)<br />{<br /> return x + (y * 4);<br />}<br /><br />float h(float x, float y) = g(f(y), x);<br /></pre><br />That last line is totally bogus C++. But... what if it <em>wasn't</em>? What would it mean if it were real and legal?<br /><br />Well, actually, it wouldn't be too amazing, because you can do:<br /><pre><br />float h(float x, float y)<br />{<br /> return g(f(y), x);<br />}<br /></pre><br /><br />But, what you can't do is:<br /><pre><br />void main()<br />{<br /> float h(float x, float y) = g(f(y), x);<br /><br /> h(4, 5);<br />}<br /></pre><br /><br />You cannot <em>dynamically</em> define functions. And that is the fundamental difference between functional programming and procedural programming.<br /><br />In functional programming, functions can be thrown around, created, destroyed, composed, etc. They're no different from any other construct; they're just like an integer, a float, or an object.<br /><br />So, back to that question: what would it mean for C++ if you could do this? Forget the fact that we defined this all as math so far; it's now just C++ function calls. In fact, the math stuff <em>is</em> C++ function calls. After all, operator +, *, etc will call functions when provided with objects for operands. So even those are function calls.<br /><br />Now that you understand what functional programming is, next time we'll discuss what you could do with it if it worked in C++. In the third article, we'll discuss, well, turning this from an academic "what if" into the truth: that C++ is very capable of all of this. Once you use the right library, of course.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-76010022113942957572006-11-03T23:55:00.000-08:002006-11-07T11:29:41.355-08:00C++ and Taking it to the LimtSo, what's the point of this Blog?<br /><br />I'm a C++ programmer, working in the programming industry. Programmers are a pretty intelligent lot. Programming is a meritocracy; if you can't hack it, you just don't get in.<br /><br />And yet, you cannot find more conservatism among programmers than you do among C++ programmers. Nobody wants to touch templates at all. Or, if they do, it's only in the most basic, simplistic way as in STL containers (vector, list) and nothing more than that.<br /><br />You don't get that with other languages. You don't see C# programmers categorically avoiding delegate functions and event handlers. You don't see Java programmers flee at the very mention of serialization or other such things. Lua programmers don't shiver in fear of using coroutines, meta-tables, or other language features. They look on these as just tools, to be used where appropriate and to not be forced into places when not.<br /><br />Why do you get this attitude with C++? Well, it's simple really. You hear horror stories (and I've experienced some of them) of some programmer having to deal with some incredibly obtuse piece of C++ code. You know the kind; the code that uses templates far more than is needed. The kind where following the code at all is virtually impossible, even in a debugger. And heaven forbid that you have to actually debug through any of it.<br /><br />It has been long said that you can shoot yourself in the foot with C, but C++ gives you the ability to take off your whole leg. So the conservatism is understood.<br /><br />But more than anything, it is an anathema to programming. C++ is capable of so much, yet so many C++ programmers use C++ as though it were merely C with language support for OOP.<br /><br />There are a lot of alternatives to C++ these days. C#, Java, even scripting languages like Python and Lua are considered alternatives to C++ in some circles. The primary advantage of C++ over those languages is raw speed. Yet so many programmers look at C++ for performance and believe that it just doesn't matter. That the ease-of-use of other languages outweighs these concerns. And if you need performant code, you should use straight C, because it is more standardized (in terms of compiled binaries).<br /><br />I understand that point of view, but I disagree with it. C++ can get most of that ease-of-use, but not if you pretend that it's just C with objects.<br /><br />For example, did you know that you can write functional programming in C++? I don't mean something kinda like functional programming; I mean just about the whole thing. Taking functions and applying functions to them to get new composite functions. You can get closures, but you'll sacrifice the look of your code. You need to download a header library to do all of this, but that's all.<br /><br />You can write a parser in C++, directly translating an Enhanced Backus-Naur Form context-free grammar into C++ instructions. You can bind functions to a scripting language without any code generation; purely through the C++ template processor. You can write C++ code that is virtually guaranteed never to leak memory; who needs slow nonsense like garbage collection in the face of that?<br /><br />But in order to do any of this, you have to do something that far too few conservative programmers are unwilling to do: use all of the languages features. No longer will we fear templates. No longer will we fear exception handling. No longer.<br /><br />The purpose of this Blog is to teach you how to take C++ to the very limit. To the point where it stops looking like C with objects, and fully becomes the possibilities of what C++ can really do.<br /><br />Undoubtedly, some of these features will frighten you. But remember back to when pointers frightened you? That didn't stop you from becoming comfortable with them (and if it did... well, did you come here by mistake?). If you don't want to be a programmer, don't code. If you're ready to take C++ to the Limit, then screw your courage to the sticking place and follow me.Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0tag:blogger.com,1999:blog-632535277908437204.post-26825133023222956992006-11-03T17:50:00.000-08:002006-11-15T17:58:14.182-08:00Navigating This BlogThis Blog is basically divided into a number of topics, under the "Label" section. They're mostly self-explanatory, except for one thing: Limit Science.<br /><br />This section lists all articles that are about advanced programming techniques. Most articles will be about these, and thus be in this section, but not all (not this one, for example).Nicol Bolashttp://www.blogger.com/profile/18441173035034536800noreply@blogger.com0