Monday, July 21, 2008

c++: property

Recently I'd touched an article about properties in python. They were implemented using special function property and looked very elegant:

class A(object):
  def __init__(self):
    self._x = None

  def get_x(self):
    return self._x

  def set_x(self, x):
    self._x = x

  x = property(get_x, set_x)

obj = A()
obj.x = 6    # set
print obj.x  # get
We don't have such option in c++. But it's quite simple to create one. Some implementation I saw were ugly indeed. They used a lot of code and wanted to call some routines in constructor. My version of property in c++:
#include <iostream>

template<typename T, 
         T(*s)(T &, const T &), 
         T(*g)(T &)>
class property
{
    public:
        
        T operator =(const T &nt)
        {
            return s(t, nt);
        }

        operator T()
        {
            return g(t);
        }

    protected:

        T t;
};

class A
{
    public:

        static int setter(int &i, const int &ni)
        {
            cout << "S" << endl;
            i = ni;

            return i;
        }

        static int getter(int &i)
        {
            cout << "G" << endl;

            return i;
        }

        property<int, setter, getter> p;
};

int main(int argc, char **argv)
{
    A a;

    a.p = 6;
    std::cout << a.p;

    return 0;
}
You have to define 2 static class methods(or just functions, doesn't matter) for setter and getter of the property. The modified version of class property may have default setter and getter:
template<typename T>
T setter(T &i, const T &ni)
{
    i = ni;

    return i;
}

template<typename T>
T getter(T &i)
{
    return i;
}

template<typename T, 
         T(*s)(T &, const T &) = setter<T>, 
         T(*g)(T &) = getter<T> >
class property
{
    public:
        
        T operator =(const T &nt)
        {
            return s(t, nt);
        }

        operator T()
        {
            return g(t);
        }

    protected:

        T t;
};
Now you can customize only one of them:
int getter(int &i)
{
    cout << "G" << endl;

    return i;
}

class A
{
    public:

        A(int a)
        {
            p = a;
        }


        property<int, setter<int>, getter> p;
};

Friday, June 27, 2008

gcc: statically linked shared library

Usually it's painful to distribute binaries of shared libraries across different linux distributions. They have different set of versions of shared libraries. For example if you have a library that uses libpq.so.5.0 to communicate with PostgreSQL you will fail to link against your library on distribution that has libpq.so.5.1. But there is no difference for you which to use: libpq.so.5.0 or libpq.so.5.1, anyway you will be able to connect to PostgreSQL and do DB related stuff. There is an option to compile a shared library with statically linked shared libraries in it. Let's try to build library that uses PostgreSQL's libpq: At first you just create objects for you library:

gcc -fPIC test.c -c
and compile shared library:
gcc test.o -o libtest.so -static-libgcc -shared -Wl,-soname=libtest.so\
-Wl,-static -lpq -lssl -lcrypt -lcrypto -lz
-static-libgcc is needed to link against libgcc statically[not all versions of gcc need that]. Shared libraries should go after -Wl,-static option. Be aware that you have to specify all shared libraries that can be involved on linking stage, otherwise they should be specified for binary that will be linked against libtest. Here I specified libpq, libssl, libcrypt, libcrypto, libz, to be linked statically. libpq also depends on krb5, but there's no static version of it in my distribution, so I'll link it to final binary. ldd output:
ldd libtest.so 
 statically linked
Now you can link your binary against libtest:
g++ usetest.cc -o usetest -L./ -ltest -lkrb5
That's all. ldd shows:
ldd usetest
 linux-gate.so.1 =>  (0xb7f37000)
 lib1.so => /tmp/work/lib1.so (0xb7c37000)
 libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0xb7bad000)
 libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7aca000)
 libm.so.6 => /lib/libm.so.6 (0xb7aa4000)
 libc.so.6 => /lib/libc.so.6 (0xb7964000)
 libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0xb7940000)
 libcom_err.so.2 => /lib/libcom_err.so.2 (0xb793c000)
 libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0xb7934000)
 libresolv.so.2 => /lib/libresolv.so.2 (0xb7921000)
 libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7916000)
 /lib/ld-linux.so.2 (0xb7f38000)
 libdl.so.2 => /lib/libdl.so.2 (0xb7912000)
No libpq or libssl, libcrypt, libcrypto, libz. Congratulations. As far as I know, not all versions of ld support this. I succeeded with 'GNU ld version 2.17.50.0.6 20061020' and 'GNU ld (GNU Binutils) 2.18', but failed with 'GNU ld version 2.16.1'[on x86_64]

Thursday, June 26, 2008

c++: coma operator

I use coma operator all the time:

int a, b;
for (a=1,b=1;a<3;++a,++b)
    ...
Probably some other cases. By specification coma operator allows to call a sequence of instructions where one is allowed. So
true?(++a,b+=2,a+b):(a+=2,++b,a-b)
will evaluate ++a,b+=2 and return a+b. The other awesome thing with coma that it breaks rule for necessity of braces for blocks of code. Multiply instruction can be folded into one:
if (a == b)
    a=1, cout << a+b;

c++: v-methods overloaded by semantics

Let's assume you have such classes:

class A
{
 public:
  A() {cout << "A" << endl;}
  virtual void func() {cout << "A::func" << endl;}
};

class B : public A
{
 public:
  B() {cout << "B" << endl;}
  virtual void func() {cout << "B::func" << endl;}
};

class C
{
 public:
  virtual void func(A &a) {cout << "C::func" << endl; a.func();}
};

class D : public C
{
 public:
  virtual void func(B &b) {cout << "D::func" << endl; b.func();}
};
And when you have
A *a;
C *c;

a = new B;
c = new D;

c->func(*a);
This produces:
A
B
C::func
B::func
Costructors from A and B invoked, and ... method C::func invoked even c is an instance of D. Compiler doesn't know anything about method func from D and it's not overwritten in virtual table because it has different semantics, so C::func was executed. To let compiler correctly execute D::func the prototype of D::func should take a reference to A as an argument. Class D can be defined like this:
class D : public C
{
 public:
  virtual void func(A &a) {cout << "D::func" << endl; a.func();}
};
In this case the output will be
A
B
D::func
B::func

Wednesday, June 4, 2008

c++: ABC and virtual destructors

Everybody knows about ABC(Abstract Base Class). It contains pure-virtual methods. What do programmers forget to define ABCs? Virtual destructor. Yes, virtual destructor:

class A
{
    public:
        virtual void a() = 0;
};

class B : public A
{
    public:
        virtual ~B()
        {   
            cout >> "~B" >> endl;
        }   

        virtual void a() {}
};

int
main(int argc,
    char **argv)
{
    A *i = new B;

    delete i;

    return 0;
}
In this code destructor of class B will never be called. Why? Because there wasn't defined virtual destructor in A. What you can do here? You can define pure virtual destructor:
virtual ~A() = 0;
That's not the end. You have to define it's body, because linker will produce an error that ~A was not found:
class A
{
    public:
        virtual ~A() = 0;
        virtual void a() = 0;
};

A::~A(){}

class B : public A
{
    public:
        virtual ~B()
        {   
            cout >> "~B" >> endl;
        }   

        virtual void a() {}
};

int
main(int argc,
    char **argv)
{
    A *i = new B;

    delete i;

    return 0;
}
Now ~B will be successfully called! Be careful!

c++: polymorphism techniques

Usually you define a virtual class member when you want it to be overridden in derived classes:

class A
{
    public:
        virtual void a() 
        {
            cout >> "A:a" >> endl;
        }
        void b() 
        {
            a();
        }   
};

class B : public A
{
    public:
        virtual void a() 
        {
            cout >> "B:a" >> endl;
        }
};

int
main(int argc,
    char **argv)
{
    A *i = new B;
    i->b();
    i->a();

    return 0;
}
This code will always produce
B:a
B:a
because method A::a is virtual and when method b called method B::a is executed. We got what we want. But if you want to call A::a in A::b. One of the possible ways is to make A::a non-virtual. But this may break all other things you wanted from from virtual member. The other way(and the most elegant amongst the others as for me) is to explicitly specify of which class method a should be called:
class A
{
    public:
        virtual void a() 
        {
            cout >> "A:a" >> endl;
        }
        void b() 
        {
            A::a();
        }   
};

class B : public A
{
    public:
        virtual void a() 
        {
            cout >> "B:a" >> endl;
        }
};

int
main(int argc,
    char **argv)
{
    A *i = new B;
    i->b();
    i->a();

    return 0;
}
This code will always produce
A:a
B:a
A::b will always call A::a. Here we go ;)

Tuesday, May 27, 2008

c++: virtual functions in contructors

There is a limitation on virtual function calls in constructors. If you call a virtual function in the constructor of the base class that was overridden in derived class you will be surprised. The function of base class will be called:

class A
{
    public:
        A() {function();}
        virtual void function() {cout << "A" << endl;}
};

class B : public A
{
    public:
        B() {function();}
        virtual void function() {cout << "B" << endl;}
};

int
main(int argc,
    char **argv)
{

    B b;

    return 0;
}
This code produces
A
B
output. The explanation is pretty simple, when constructor of the base class is called the derived object has not been constructed. This way c++ protects us. You don't have access to the derived class object from the the base class constructor. Only when initialization of base class was had been finished virtual table is being refreshed.

Friday, May 23, 2008

c++: reuse memory for objects

It happens when you are creating and deleting objects heavily. Like this:

    for (int i=0;i<1000000;++i)
    {   
        A *a = new A;

        //do something with 'a'

        delete a;
    }
Yup, it happens and sometimes it's a best solution. If you can't use stack memory because A is pretty big and you used almost all of the stack memory before or used a recursion. But this is extremely slow. You obtain memory fragmentation and invoke memory manager to get free chunk of memory and than free it. c++ specification allows you to reuse memory:
#include <new>

int
main(int argc, char **argv)
{
    char *memory = new char[sizeof(A)];
    void *place = memory;
    
    for (int i=0;i<1000000;++i)
    {
        A *a = new(place) A;

        //do something with 'a'

        a->~A();
    }   
}
In the code sample above A in the loop is always put into the 'memory'. The executable will request for the chunk of memory once before the loop. Depending on the code this may be more than 10 times faster. While using new() developer have to call destructor explicitly and include 'new' header manually. Anyway, if you can put A in the loop into the stack, try to do it. It the fastest and the safest way:
    for (int i=0;i<1000000;++i)
    {   
        A a;

        //do something with 'a'
    }   

Thursday, May 22, 2008

c++: default initializers

In c++.03 you are unable to call explicitly one constructor within another:

class A
{
    public:
        A(int x, int y) : x(x), y(y) {}
        A(int x) { A(x, 0); }

        int x, y;
}
This will produce compilation errors. As a workaround developers usually use an initialization function that can be called within the constructor:
class A
{
    public:
        A(int x, int y) : {init(x, y);}
        A(int x) {init(x,0);}

        int x, y;

    protected:
        void init(int a, int b) {x = a; y = b;}
}
The idea I got today is to make an abstraction of class data in base struct, derive class from the struct and initialize struct data with it's constructor. This will make things clear and will allow to separate data from its manipulation:
struct A
{
        A(int x, int y) : x(x), y(y) {}

        int x, y;
};

class B : public A
{
    public:
        B() : A(0, 0) {}
        B(int x) : A(x, 0) {}
};

c++: constructor arguments

Names of constructor arguments which will initialize class members can have the same name as class members:

class A
{
    public:
        A(int x) : x(x) {} 

        int x;
};
I used to make a prefix for constructor arguments as thought compiler will produce an error message. Yeah, now source code can be cleaner. Be aware that next code won't work:
class A
{
    public:
        A(int x) {x = x;} 

        int x;
};
Here x in constructor's body is the argument of the contructor. You will have an unexpected value of A::x each time as it not initialized. As a workaround:
class A
{
    public:
        A(int x) {this->x = x;}

        int x;
};
Here x in constructor's body is argument of constructor and this->x is A::x.

Wednesday, May 7, 2008

bash: completion

Almost everybody uses bash. It's awesome with it simplicity and power. Recently I've been introduced to bash completion in conjunction with ssh. The author proposed to use bash completion to expand list of known hosts(~/.ssh/known_hosts) for ssh. He suggested to fetch the list and feed it to 'complete' built-in bash command:

complete -W "`cat ~/.ssh/known_hosts \
| cut -d ' ' -f1 | cut -d ',' -f1 | cut -d ']' -f1 \
| sed 's/\[//' | sort`" ssh
This command will provide a fixed list. If you eventually have gone to the new host the new hostname will be lost for the completion. I've made some investigation and have found out that you can provide a function for 'complete' that will be called each time the completion requested. Here is a function:
function _ssh_comp()
{
CUR="${COMP_WORDS[COMP_CWORD]}";
COMPREPLY=( $(compgen -W "$(gawk 'BEGIN {i=0}\
{split($1,nodes,",");\
gsub("([[]|[]]:?[0-9]*)","",nodes[1]);\
hosts[i++]=nodes[1]}\
END {for (j in hosts) {print hosts[j]}}' ~/.ssh/known_hosts)" -- ${CUR}) );
return 0;
}
From the bash reference:
We can read the description of COMPREPLY
An array variable from which Bash reads the possible completions generated by a shell function invoked by the programmable completion facility
We can also see how we found the current word using the array COMP_WORDS to find both the current and the previous word by looking them up
An array variable consisting of the individual words in the current command line. This variable is available only in shell functions invoked by the programmable completion facilities.
COMP_CWORD
An index into ${COMP_WORDS} of the word containing the current cursor position. This variable is available only in shell functions invoked by the programmable completion facilities
Then you should tell 'complete' to use this function:
complete -o default -F _ssh_comp ssh
I typed 'ssh 1' then pressed and here we go:
$ssh 192.168.229.1
192.168.229.128  192.168.229.130  192.168.229.132  192.168.229.134  192.168.229.137  192.168.229.140  192.168.229.145  
192.168.229.129  192.168.229.131  192.168.229.133  192.168.229.136  192.168.229.138  192.168.229.144  192.168.229.146

Wednesday, April 30, 2008

c/c++: switch vs. array of functions

As I promised I made some tests to compare switch statement and a map to functions. As I expected a map to functions works faster. Furthermore it doesn't depend on the amount of 'switch' conditions. I made a synthetic test:

unsigned long func(unsigned long acc)
{
    return acc*acc;
}

#define SWITCH

typedef unsigned long (*fd)(unsigned long);

int main(int argc, char **argv)
{
    unsigned long i, acc = 0;

    #ifndef SWITCH
        fd f[15] = {func,func,func,func,func,func,func,func,func,func,func,func,func,func,func};
    #endif

    for (i=0;i<1000000000;++i)
    {   
        #ifdef SWITCH
            switch (i%15)
            {
                case 0:
                    acc = func(acc + i); break;
                case 1:
                    acc = func(acc + i); break;
                case 2:
                    acc = func(acc + i); break;
                case 3:
                    acc = func(acc + i); break;
                case 4:
                    acc = func(acc + i); break;
                case 5:
                    acc = func(acc + i); break;
                case 6:
                    acc = func(acc + i); break;
                case 7:
                    acc = func(acc + i); break;
                case 8:
                    acc = func(acc + i); break;
                case 9:
                    acc = func(acc + i); break;
                case 10: 
                    acc = func(acc + i); break;
                case 11: 
                    acc = func(acc + i); break;
                case 12: 
                    acc = func(acc + i); break;
                case 13: 
                    acc = func(acc + i); break;
                case 14:
                    acc = func(acc + i); break;
            }
        #else
            acc = f[i%15](acc + i);
        #endif
    }

    return 0;
}
Times w/o switch:
$for i in 1 2 3; do time ./a.out; done

real 0m11.114s
user 0m10.973s
sys 0m0.010s

real 0m10.968s
user 0m10.966s
sys 0m0.007s

real 0m10.904s
user 0m10.899s
sys 0m0.003s
and w/ switch
$for i in 1 2 3; do time ./a.out; done

real 0m12.378s
user 0m12.399s
sys 0m0.000s

real 0m12.410s
user 0m12.413s
sys 0m0.013s

real 0m12.417s
user 0m12.423s
sys 0m0.010s
A map to functions wins ~1 sec. That's not that much but if you are building a state machine with a lot of states it's better to use mapping rather than switch.

c++: friend classes in namespaces

You can declare friend class w/o declaration of it:

class A{friend class B;}
Here compiler doesn't have to know what is class B. But things go worth if you have class A defined in namespace N and class B in namespace M, or in other words A and B are in different namespaces. If you leave the things and you don't want to include header with declaration of class B, compiler will argue that class M::B doesn't have an access to private/protected members of N::A. You can't simply do
namespace N{ class A{friend class M::B;} };
Here compiler will raise an error that there is no B in namespace M, or even no such namespace 'M' if it hasn't achieved it during parsing. The solution here is to do a declaration of empty class B in namespace M:
namespace M{class B;}; namespace N{ class A{friend class M::B;} };
This will work and your compiler will be happy ;)