<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Andrew Jenner's WebLog</title><subtitle type="html">Modern programming techniques</subtitle><id>http://blogs.msdn.com/ajenner/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/ajenner/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/ajenner/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2004-07-29T16:02:00Z</updated><entry><title>Operator overloading</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/ajenner/archive/2004/08/05/209312.aspx" /><id>http://blogs.msdn.com/ajenner/archive/2004/08/05/209312.aspx</id><published>2004-08-05T22:05:00Z</published><updated>2004-08-05T22:05:00Z</updated><content type="html">&lt;P&gt;Continuing along the lines of the &amp;#8220;say what you mean&amp;#8220; style of programming, let's look at a naming convention for certain types of functions which more accurately reflects what they mean. Last time, we saw a function for adding two 128 bit numbers:&lt;/P&gt;&lt;PRE&gt;int128 sum_of_128bit_numbers(int128 x,int128 y)
{
    int128 z;
    z.low = x.low + y.low;
    z.high = x.high + y.high;
    if (z.low &amp;lt; x.low)
        ++z.high;
    return z;
}&lt;/PRE&gt;
&lt;P&gt;and some code which calls it:&lt;/P&gt;&lt;PRE&gt;    z = sum_of_128bit_numbers(x,y);&lt;/PRE&gt;
&lt;P&gt;One way we can improve this is to write the function as an overloaded operator:&lt;/P&gt;&lt;PRE&gt;int128 operator+(int128 x,int128 y)
{
    int128 z;
    z.low = x.low + y.low;
    z.high = x.high + y.high;
    if (z.low &amp;lt; x.low)
        ++z.high;
    return z;
}&lt;/PRE&gt;
&lt;P&gt;Then the syntax to call it is just:&lt;/P&gt;&lt;PRE&gt;    z = x + y;&lt;/PRE&gt;
&lt;P&gt;which I'm sure you'll agree is much simpler, especially when you have lots of overloaded operators and a complex expression. Which would you rather read/write/review/maintain, this:&lt;/P&gt;&lt;PRE&gt;    z = x*x + y*y;&lt;/PRE&gt;
&lt;P&gt;or this:&lt;/P&gt;&lt;PRE&gt;    z = sum_of_two_128_bit_numbers(product_of_two_128_bit_numbers(x,x),product_of_two_128_bit_numbers(y,y));&lt;/PRE&gt;
&lt;P&gt;?&lt;/P&gt;
&lt;P&gt;Programmers who are used to a programming language which doesn't offer operator overloads tend to be&amp;nbsp;rather horrified at this concept the first time they see it (I know I was).&amp;nbsp;They say things like &amp;#8220;but this means I can't tell what even the simplest pieces of code really do just by looking at them&amp;#8221;. I'd argue that this ability is overrated. Modern programming is all about abstraction. We don't need to know every single detail about what's going on in a particular line of code. We don't need to know the mechanics of how addition works to understand a line of code like:&lt;/P&gt;&lt;PRE&gt;    z = x + y;&lt;/PRE&gt;
&lt;P&gt;We also don't need to know which registers the compiler decides to assign to which variables (if we did we'd be writing in assembly language, not C++). Nor do we&amp;nbsp;need to know how numbers are represented in binary by the computer's hardware, nor the details&amp;nbsp;of the logic gates and transistors used in the CPU's addition circuitry, nor the voltage levels in the processor nor any one of a million little details which all have to work out in order that we can add two numbers. All we need to know is the highest level concept - we're adding these two numbers. And that fact is best expressed by the statement:&lt;/P&gt;&lt;PRE&gt;    z = x + y;&lt;/PRE&gt;
&lt;P&gt;Now, I do agree that it is possible to abuse that power and write code which is almost impossible to follow, for example by writing an &amp;#8220;operator+&amp;#8221; function that does something entirely different from addition. But you can write bad code in any language. You can do similarly evil things even in C:&lt;/P&gt;&lt;PRE&gt;int128 sum_of_128bit_numbers(int128 x,int128 y)
{
    int128 z;&lt;BR&gt;    // Haha! We lied and will actually XOR the two numbers!
    z.low = x.low ^ y.low;
    z.high = x.high ^ y.high;
    return z;
}&lt;/PRE&gt;
&lt;P&gt;The problem here is that the function doesn't do what it says, not that operator overloading is intrinsically evil. The name &amp;#8220;operator+&amp;#8220; is just that - a name. It's&amp;nbsp;a name which implies certain things about the semantics of the function in question, just like any good name should. It also allows callers of&amp;nbsp;this code to employ certain syntactic sugar - they can write:&lt;/P&gt;&lt;PRE&gt;    z = x + y;&lt;/PRE&gt;
&lt;P&gt;instead of:&lt;/P&gt;&lt;PRE&gt;    z = operator+(x,y);&lt;/PRE&gt;
&lt;P&gt;(The latter is completely valid C++ code, by the way, though rarely more appropriate than the former).&lt;/P&gt;
&lt;P&gt;There is one other argument against operator overloading - that is that it makes it more difficult to see the performance bottlenecks in a program.&amp;nbsp;Maybe you have an &amp;#8220;operator+&amp;#8221; which adds large matrices together, and could potentially be quite slow if the matrices are large. You wouldn't necessarily expect a simple &amp;#8220;x+y&amp;#8221; expression to be slow, if you're used to programming in C where such expressions typically cause the compiler to emit only one or two machine language instructions.&lt;/P&gt;
&lt;P&gt;The counter-argument is that we should not expect the names of functions to reflect how long they take to run (otherwise we'd be writing functions with names like &amp;#8220;add_two_128bit_numbers_takes_about_20_cycles_to_run&amp;#8221;) which would be a maintainance nightmare (imagine&amp;nbsp;if every time you changed the implementation of&amp;nbsp;a function you had to change the name of that function and every function that called it!). No, use the right tool for the job - visually inspecting a program isn't the right way to figure out where the performance bottlenecks are. Use a profiler instead.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=209312" width="1" height="1"&gt;</content><author><name>ajenner</name><uri>http://blogs.msdn.com/members/ajenner.aspx</uri></author></entry><entry><title>std::cout &lt;&lt; "Hello, World!" &lt;&lt; std::endl;</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/ajenner/archive/2004/07/29/201165.aspx" /><id>http://blogs.msdn.com/ajenner/archive/2004/07/29/201165.aspx</id><published>2004-07-29T23:02:00Z</published><updated>2004-07-29T23:02:00Z</updated><content type="html">&lt;P&gt;Hello! My name is Andrew Jenner and I'm a Software Design Engineer (SDE) in the &lt;A href="http://blogs.msdn.com/vsdteam/"&gt;Visual Studio Devices team&lt;/A&gt;. I work on IDE functionality for managed projects (though some of the components I have written are also used by the native project system).&lt;/P&gt;
&lt;P&gt;However, for the most part this blog isn't going to be about programming for Smart Devices, programming for the .NET Compact Framework or even .NET programming in general. Instead I'm going to be writing about what I know best - C++ programming techniques, and general programming techniques that can be applied in most languages.&lt;/P&gt;
&lt;P&gt;To start off, here's a programming principle that seems to me to be so fundamental that it is often forgotten: &lt;B&gt;Say what you mean&lt;/B&gt;.&lt;/P&gt;
&lt;P&gt;What do I mean by this? Well, let's start off with a simple example. Suppose you have some code like this:&lt;/P&gt;&lt;PRE&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;iomanip&amp;gt;&lt;/PRE&gt;&lt;PRE&gt;typedef long long int64;
typedef unsigned long long uint64;&lt;/PRE&gt;&lt;PRE&gt;struct int128
{
    int64 high;
    uint64 low;
};&lt;/PRE&gt;&lt;PRE&gt;int main()
{
    int128 x={10,20}, y={30,40}, z;&lt;/PRE&gt;&lt;PRE&gt;    z.low = x.low + y.low;
    z.high = x.high + y.high;
    if (z.low &amp;lt; x.low)
        ++z.high;&lt;/PRE&gt;&lt;PRE&gt;    std::cout &amp;lt;&amp;lt; std::hex &amp;lt;&amp;lt; std::setw(16) &amp;lt;&amp;lt; std::setfill('0') &amp;lt;&amp;lt; z.high;
    std::cout &amp;lt;&amp;lt; std::setw(16) &amp;lt;&amp;lt; std::setfill('0') &amp;lt;&amp;lt; z.low &amp;lt;&amp;lt; std::endl;
}
&lt;/PRE&gt;
&lt;P&gt;What does this code actually do? Well, it may not be obvious at first sight because it doesn't actually &lt;I&gt;say&lt;/I&gt; what it does. But compare this slightly modified version:&lt;/P&gt;&lt;PRE&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;iomanip&amp;gt;&lt;/PRE&gt;&lt;PRE&gt;typedef long long int64;
typedef unsigned long long uint64;&lt;/PRE&gt;&lt;PRE&gt;struct int128
{
    int64 high;
    uint64 low;
};&lt;/PRE&gt;&lt;PRE&gt;int128 sum_of_128bit_numbers(int128 x,int128 y)
{
    int128 z;
    z.low = x.low + y.low;
    z.high = x.high + y.high;
    if (z.low &amp;lt; x.low)
        ++z.high;
    return z;
}&lt;/PRE&gt;&lt;PRE&gt;int main()
{
    int128 x={10,20}, y={30,40}, z;&lt;/PRE&gt;&lt;PRE&gt;    z = sum_of_128bit_numbers(x,y);&lt;/PRE&gt;&lt;PRE&gt;    std::cout &amp;lt;&amp;lt; std::hex &amp;lt;&amp;lt; std::setw(16) &amp;lt;&amp;lt; std::setfill('0') &amp;lt;&amp;lt; z.high;
    std::cout &amp;lt;&amp;lt; std::setw(16) &amp;lt;&amp;lt; std::setfill('0') &amp;lt;&amp;lt; z.low &amp;lt;&amp;lt; std::endl;
}
&lt;/PRE&gt;
&lt;P&gt;Now we can immediately see that this code implements addition of high precision integers. The simple act of naming the 4 mysterious lines of code (by putting them in a function with a descriptive name) has made the program much easier to understand (more so, I would argue, than an equivalent comment that just explains what those 4 lines of code do).&lt;/P&gt;
&lt;P&gt;This change doesn't make any difference to the compiler (especially if it implements Named Return Value Optimization or chooses to inline the sum_of_128bit_numbers() function) but it greatly improves the readability of the program for humans. It's easy to write a program that a computer can understand (just change things until it compiles) but writing programs that are easy for people to understand is much more difficult. Since any non-trivial program will eventually need to be maintained, we should strive to make all our code as easy to read by humans as possible.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=201165" width="1" height="1"&gt;</content><author><name>ajenner</name><uri>http://blogs.msdn.com/members/ajenner.aspx</uri></author></entry></feed>