Thursday, July 28, 2011

Gotcha in C++ Function Overloading

Suppose we have this code.
#include <iostream>
using namespace std;

class Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Base: " << a << endl;
    }
    virtual void doSomething(int a) {
        cout << "This is int from Base: " << a << endl;
    }
    virtual ~Base() {}
};

class Derived : public Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Derived: " << a << endl;
    }
    virtual ~Derived() {}
};

int main() {
    Derived d;

    int i = 2;
    double j = 0.1;
    d.doSomething(i);
    d.doSomething(j);

    return 0;
}
We would expect the output to be:
This is int from Base: 2
This is double from Derived: 0.1

Strangely, the output is:
This is double from Derived: 2
This is double from Derived: 0.1

The way overload resolution works in C++ is that the compiler will first search for function doSomething() inside the Derived class. If it finds it, it will stop there; otherwise it will look the one in the Base class for a matching function. To solve this problem, we need to add using Base::doSomething in order let it participate in the overload resolution.
#include <iostream>
using namespace std;

class Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Base: " << a << endl;
    }
    virtual void doSomething(int a) {
        cout << "This is int from Base: " << a << endl;
    }
    virtual ~Base() {}
};

class Derived : public Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Derived: " << a << endl;
    }
    using Base::doSomething; 
    virtual ~Derived() {}
};

int main() {
    Derived d;

    int i = 2;
    double j = 0.1;
    d.doSomething(i);
    d.doSomething(j);

    return 0;
}

The output is:
This is int from Base: 2
This is double from Derived: 0.1

Wednesday, July 27, 2011

Basic SVN Commands

Here I'm gonna show you some basic SVN commands with some examples.

Checking out
svn co http://[hostname]/trunk

Checking in
svn ci

Viewing SVN information
This will display information, such SVN URL, revision number, etc.
svn info

Viewing SVN status
This will display information, such as files modified, added, deleted, etc.
svn status

Updating the local SVN repository
svn up

Viewing the diff
svn diff

Viewing SVN logs
svn log

Adding a file into SVN
svn add new_file.txt

Moving/Renaming a file from one place to another place
svn move old_file.txt new_file.txt

Deleting a file from SVN
svn del junk_file.txt

Reverting local changes in a file
svn revert whatever_file.txt

Reverting local changes recursively
svn revert -R *

Creating a branch/tag
svn copy http://[hostname]/trunk http://[hostname]/branches/1.0
svn copy http://[hostname]/trunk http://[hostname]/tags/1.0

De-commiting changes in the trunk
This will first do a diff between HEAD and rev 123 in the trunk and then do a dry-run before performing an actual merge.
svn diff -r HEAD:1234 http:/[hostname]/trunk
svn merge -r --dry-run HEAD:1234 http:/[hostname]/trunk
svn merge -r HEAD:1234 http:/[hostname]/trunk
svn ci

Merging changes from the branch to the trunk
Assume that the current directory is where the trunk code was checked out.
svn diff -r 1234:HEAD http://[hostname]branches/1.0
svn merge -r 1234:HEAD --dry-run http://[hostname]/branches/1.0
svn merge -r 1234:HEAD http://[hostname]/branches/1.0
svn ci

Merging changes from the trunk to the branch
Assume that the current directory is where the branch code was checked out.
svn diff -r 1234:HEAD http://[hostname]/trunk
svn merge -r 1234:HEAD --dry-run http://[hostname]/trunk
svn merge -r 1234:HEAD http://[hostname]/trunk
svn ci

Viewing SVN externals
svn propset svn:externals .

Editing SVN externals
svn propedit svn:externals .

Viewing who modified the file
svn blame whosefault.txt