Bug Vanquisher

25 October 2008

C++: Another Love Story

Filed under: C++ — Tanveer Badar @ 1:21 AM

After many moons, the story is like this:

Given,

    int array [ 12 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 };

The sequence of function calls

    // reflexive returns true, is_prime is true for primes (hard-coded for now) and is_even returns true for even numbers.
    abc = query::as_query( abc ).where( reflexive( ) ).where( is_prime( ) ).where( is_even( ) ).to_array( );

    for( int i = 0 ; i < abc.size( ) ; ++i )
        std::cout << abc [ i ] << ‘ ‘;

prints 2. Btw, there was a serious bug in the implementation of where( ) which is fixed now.

Additionally,
>    Query.exe!query::queryable<
                            query::filter_iterator<
                                query::filter_iterator<
                                    std::_Vector_iterator<int,std::allocator<int> >,
                                                        reflexive>,
                            is_prime> >::
                    where<is_even>(const is_even & fn={…})  Line 240    C++

This should prove delayed execution I believe. Now, all I have to do is wait for lambda expressions in C++, coming sometime next year.

24 May 2008

C++ – The Power of Templates

Filed under: C++ — Tanveer Badar @ 5:52 PM

Do you read Ian Griffiths? If not, please start reading. Belongs in the group of smart people (by my classification).

But smarties don’t know everything either, nor do I. However, there is one thing Ian gets wrong in one of his articles. He specifically writes,

The fact that there is no implied type becomes even more striking when you consider some more interesting Python examples. Because Python performs its type checks even later than C++, you have even more flexibility:

def speak(speaker, mood):
    if mood == "verbose":
        speaker.WaxLyrical()
    elif mood == "shy":
        speaker.Whisper()
    else:
        speaker.Talk()

yada yada yada…

Note that in C++ we’d see a different result here. Python defers its type checking until the point at which you try to use a member. In a C++ template, the check is done when the template is instantiated. So C++ would actually require all three methods to be present, despite the fact that only one will be used for any given execution of the speak method. So in C++ the constraints a template can impose on its parameter are less dynamic than in Python.

However, the part about "C++ would actually require all three methods to be present" is wrong assertion. It is entirely possible to have the same behavior like Python in C++. Never, ever, underestimate the power of compile time Turing-complete templates available. :)

The code given below requires only one function at a time. My only humble request is to compile it on a sane compiler (implicitly exclude MSVC 7 and earlier).

#ifdef _MSC_VER && _MSC_VER <= 1300

#error Can’t you read English. THIS STUFF REQUIRES MSVC 8 OR HIGHER!!!

#endif

struct A { void whisper( ) { } };

struct B { void shriek( ) { } };

struct C { void snarl( ) { } };

template< typename T > struct invoker

{

    static void invoke( T )

    {

    }

};

template< > struct invoker< A >

{

    static void invoke( A obj )

    {

        obj.whisper( );

    }

};

template< > struct invoker< B >

{

    static void invoke( B obj )

    {

        obj.shriek( );

    }

};

template< > struct invoker< C >

{

    static void invoke( C obj )

    {

        obj.snarl( );

    }

};

template< typename T > void f( T obj )

{

    invoker< T >::invoke( obj );

}

void g( )

{

    f( A( ) );

}

Hopefully, a little more C++ will bring peace and harmony in the world :). One can only hope.

13 April 2008

It is coming

Filed under: C++ — Tanveer Badar @ 7:52 PM

int array [ ] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 };
std::vector< float > v( query::as_query( array , array + 12 ).select( 5.3f ).to_array( ) );
std::copy( v.begin( ) , v.end( ) , std::ostream_iterator< double >( std::cout , ” ” ) );
std::cin.get( );

The first revision is here!

Compare the above to this. Almost all the clutter is gone.

7 April 2008

Analyze This!

Filed under: Bugz, C++ — Tanveer Badar @ 1:06 AM

Consider this little piece of ****. I mean piece of code. :)

template< typename U , typename T > U convert( T t )
{
    return t;
}

template< typename T , typename projection , > class blah_blah_blah
{
public:
    // details we really shouldn’t see

    projection& operator * ( )
    {
        return convert< projection >( *current );
    }
};

If you decide to do

blah_blah_blah< float , double > x = get_blahblahblah( );
*x;

The second statement will fail with some cryptic error message. The real problem is the return type of operator * and the statement return t; in convert. The implicit conversion from T to projection (which is to say, promotion from float to double) loses the l-value[dness] of *current. And since a reference requires l-value upon return, it fails to compile.

Given the constraint the convert< projection > was absolutely necessary, and upon further thought, that projection& was not a requirement, a fix was born.

projection operator * ( )
{
    return convert< projection >( *current );
}

20 January 2008

Extreme Meta-programming

Filed under: C++ — Tanveer Badar @ 6:05 PM

“It was one of my most brilliant ideas, and between you and me, that’s saying something….My brain surprises even me sometimes…”

Albus Dumbledore – Harry Potter and The Philosopher’s Stone

What should this quote be doing here. Well I had a similar idea 30 minutes ago, out of which it took 15 minutes to write this post and get the two references. You see, in C++, iterators are a core concept related to streams and container. They may get redesigned a bit in near future (or may already have) but the notion will not change.

At the beginning, there was one, the input_iterator. It can only go forward and be dereferenced only once. Then came, the forward_iterator, it can also only go forward but can be dereferenced multiple times. This evolved into bidirectional_iterator, which can move in either direction and is a forward_iterator. Finally, the chain terminates at random_access_iterator which allows random access, chiefly [ ] and +, -, in addition to being a bidirectional_iterator.

With this background, I was writing a class which needed distinguished behavior depending upon the iterator type specified as a template argument. I thought, and kept thinking about it as to how should I approach the problem. I had already said a big “no” to partially specializing it, or any of the base classes, upon iterator type.

Therefore, the distinguishable functionality now resides in a separate class. I decided not to support input_iterator. Hierarchy starts at forward_iterator and goes hands in hands with other three.

Sorry about the cryptic text, that’s the spirit of C++ I like most.

template< typename iter , typename projection , typename category = std::forward_iterator_tag > class projection_iterator : public std::iterator< category , projection , typename std::iterator_traits< iter >::difference_type , typename std::iterator_traits< iter >::pointer , typename std::iterator_traits< iter >::reference >
{

// things like ++ (pre,post), *, ->, == and !=.

};

// This gets rid of input_iterator. Any attempts to instantiate will result in compile time error of type not defined.

template< typename iter , typename projection > class projection_iterator< iter , projection , std::input_iterator_tag >;

template< typename iter , typename projection > class projection_iterator< iter , projection , std::bidirectional_iterator_tag > : public projection_iterator< iter , projection , std::forward_iterator_tag >
{

// inherits from general class, adds — (pre,post).

};

template< typename iter , typename projection > class projection_iterator< iter , projection , std::random_access_iterator_tag > : public projection_iterator< iter , projection , std::bidirectional_iterator_tag >
{

// inherits from bidirectional_iterator case, adds [ ], +, -.

};

With implementation inheritance, I have reduced the amount of code I would have written otherwise quite drastically.

[Nitpickers corner]

It is still a work in progress. I, most specifically, don’t want any comment from you or bugging me on IM.

14 January 2008

C++ Needs Serious Variable Inferencing

Filed under: C++ — Tanveer Badar @ 1:40 AM

A little excerpt from a little project of mine.

int array [ 5 ] = { 0 , 1 , 2 , 3 , 4 };
query::as_query( array , array + 5 ).select< query::actions::identity< int* > >( )
    .where( query::actions::condition< query::actions::identity< int* > , std::less< int > >( std::less< int >( ) ) )
    .orderby< query::actions::order< query::actions::condition< query::actions::identity< int* > , std::less< int > > > >( );

Those who can See will notice what is going on here given my history. Apart from that, notice how template arguments have gone out of hand with only three consecutive function calls. Consider the chaos when you bring in the big brothers, groupby, *join, subqueries and so on.

C++ seriously needs variable inferencing. I cannot wait to get my hands on a compiler which supports auto (no pun) type deduction. Above snippet is with no functionality and only compiling on bare bones at the moment. That library isn’t even functional and things will definitely get messier when it actually does something.

[Update]

Some 20 minutes later, the glue has been reduced by a great amount due to clever hard coding to condition in where definition.

query::as_query( array , array + 5 ).select< query::actions::identity< int* > >( )
    .where( std::less< int >( ) )
    .orderby< query::actions::order< query::actions::condition< query::actions::identity< int* > , std::less< int > > > >( );

2 December 2007

Every Problem in Software can be Solved with Another Layer of Indirection

Filed under: C++ — Tanveer Badar @ 11:26 PM

How true! I keep rediscovering this fact over and over again.

As an example, consider the problem of virtual function invocation during object construction and destruction in C++. A virtual function resolves to the type of running constructor/destructor even if it has been overridden in derived classes. Apparently, C# and Java do not suffer from this particular ailment because their object type is always the most derived during constructions. Sadly they do not have destructors and have much worse problems than not being able to call proper virtual functions.

This limitation (actually a very good thing) stems from the fact that a constructor set vtable in the object to only its current type as it does not know what further derives from that type. Similarly, a destructor sets vtable to point to implementations in the current type because derived class sub-object has been destroyed by the time destructor for a base class runs.

Aside from this minor annoyance, it is part of a larger problem too. Pure virtual function calls fail during construction/destruction.

Therefore, how to overcome this particular obstacle. A very simple case is performing parameter validation in constructor. This cannot possible depend on state information as there is none at the moment.

The workaround is just around the corner. Introduce a parallel class hierarchy that performs validation, for the hierarchy under consideration acts as factories and pass a base class reference/pointer in constructors. Even passing state is possible through references and pointer or directly by copying if the object is copy-constructible.

Some code is in order here.

struct base
{
    base( int param )
    {
        validate( param );
    }

    virtual void validate( int value )
    {
        if( value < 0 )
            throw invalid_argument( "value cannot be less than zero." );
    }
};

struct derived : public base
{
    derived( int param ) 
        : base( param )
    {
    }

    void validate( int value )
    {
        base::validate( value );
        if( value > 5 )
            throw invalid_argument( "value cannot be greater than five." );
    }
};

This problem with this code derived( 10 ) passes validation because derived::validate is never called.

With the validation code moved to parallel class hierarchy we avoid this problem because those objects have already passed their construction phase.

struct basevalidator
{
    virtual void validate( int value )
    {
        if( value < 0 )
            throw invalid_argument( "value cannot be less than zero." );
    }
};

struct derivedvalidator : public basevalidator
{
    void validate( int value )
    {
        base::validate( value );
        if( value > 5 )
            throw invalid_argument( "value cannot be greater than five." );
    }
};

struct base
{
    base( int param )
    { 
        basevalidator( ).validate( param );
    } 

protected:
    base( int param , const basevalidator& validator )
    {
        validator.validate( param );
    }
};

struct derived : public base

    derived( int param ) 
        : base( param , derivedvaliator( ) )
    {
    }
};

4 November 2007

CppCodeProvider Bug List

Filed under: Bugz, C++ — Tanveer Badar @ 7:57 PM

Despite making major strides in the implementation of CppCodeProvider there are still some pieces missing. There are still few cases where you get no definition when rendering UDTs split. Specific cases are:

  • Foremost, MemberType and PointerToMember  will throw FunctionNotImplementedException if rendered.

  • Member types (UDT/enum/union) which are not specified to be defined inline are missing definitions.

  • I would love to add support to declare a function/type as friend of another UDT or union.

  • If a member variable is declared static const and not an integral type, it is not defined.

  • If a member function (function/operator/constructor/destructor) is not declared inline

Irrelevant of rendering UDTs split or not, member type and pure virtual function rendering is broken and here is why:

  • If a member UDT has enclosing type as one of the bases, it is not even defined.

  • If a member function is pure (exception constructors), it is not defined anywhere.

Apart from these, there is memory leak when you try to assign a destructor to a UDT. I am investigating that issue.

Jubilant

Filed under: C++ — Tanveer Badar @ 7:57 PM

I am very happy to announce that CPPCodeProvider is almost complete in implementation. The first beta release will be available at the download site shortly, hosted by source forge. And as time is passing, this post is becoming more and more of a wish list than some sort of release notes. A separate post on current bugs follows.

The reason it took so long to complete was due to me being lazy. The last functions were the largest to write, the hardest to work out and most important, without them it was impossible to write out a user defined type.

Also, I have done some more prettification for final code rendering. A bug which lay undiscovered so far has been fixed. It involved instantiating a type with bool which was not recognized and threw invalid_argument exception.

Two things I would like to note are: I have made the way code is indented in the output stream(s). Each class now dictates its own indentation by using tabs argument and no one else does that work for it. Additionally, if any CodeObject needs to have newline rendered after it, that newline must be rendered by the calling code because most of the time, it is out of context to know if a newline will not disturb the indentation and formatting.

After these two changes there should be no formatting problems as far as I can say. However, if you do see something messed up missing newlines or incorrect indentation, drop me a line on sourceforge about that specific CodeObject and if possible, some CodeDOM to reproduce the issue.

One more thing to note is the behavior of constructors of copying_pointer. Both constructors which take T* and T& own the passed argument. Therefore, be very careful if you do this:

copying_pointer< T > a( new T ) , b( *a );

This line will cause T to be deleted twice and if you are lucky this will be caught during debug builds. Correct way is to write

copying_pointer< T > a( new T ) , b( a );

because the copy constructor makes a copy of passed argument, hence no ownership issues. Similarly, UDT will own the destructor assigned to it. Be careful with that after memory leak is fixed.

I am also working on efficiently implementing BasicType. It’s purpose is to model primitive types which are only handful and rarely change. Therefore, it would be wise to have a cache of BasicType which handed out an object given the type name. But I will need to further investigate as it will undoubtedly introduce race conditions during cache initialization.

Also, next time there will be support to indent using either tabs or space.

31 October 2007

First Love

Filed under: C++, Fun — Tanveer Badar @ 11:13 PM

Just read it on Jim Galasyn’s blog.

                                         it’s back to my first love, C++.

I must say, mine too while adding foremost and forever!

Older Posts »

Blog at WordPress.com.