Date: prev next · Thread: first prev next last
2011 Archives by date, by thread · List index


On Wednesday 23 of November 2011, Michael Meeks wrote:
On Wed, 2011-11-23 at 14:56 +0100, Lubos Lunak wrote:
 And some of the arguments are rather weak as well, I can get you easy to
use and read, better to translate and similarly space efficient without
var-args. Wanna bet :) ?

      Sounds great to me; of course - it'd be nice if it compiled in linear
time too without including a million lines of odd boost templated
headers ;-) but certainly; if we can get something readable, and
typesafe that compiles to something -actually-small- - ie. a single
function call & setup; I'm all for it whatever it looks like - it sounds
like the best of all worlds.

 I haven't thought it out in detail, but the general idea is attached. It's 
just a proof of concept, so there are some obvious problems, but I don't see 
a flaw in the design. Since it's also just a single call, the in-place cost 
is small and is moved to the bodies of the templates, which can be just in 
one place, one per each combination of arguments (and the common instances of 
the template can be externed, so it really will be just one copy). The 
template code is relatively small, so I don't expect noticeable impact on 
compile time. Also, funnily enough, the generated code in the place of the 
call is one instruction shorter, because unlike printf() it does not need the 
terminating NULL for the vararg :).

 I expect it would be even possible to achieve such single in-place call even 
for the LOG( "P is " << p << " and b is " << b ) case, or even do this for 
string+string operation, which would turn it into the even better-looking 
LOG( "P is " + p + " and b is " b ) or LOG( "P is %1 and b is %2", p, b ), 
whichever would suit one's fancy (as in, both would be possible at the same 
time). It would require getting a bit more creative with argument and return 
types for the operator overloads, but that'd be hidden behind the scenes.

-- 
 Lubos Lunak
 l.lunak@suse.cz
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>

class formater_base
    {
    public:
        virtual void format( char* buffer ) const = 0;
    };

template< typename T >
class formater : public formater_base
    {
    public:
        formater( T data ) : data( data ) {}
        virtual void format( char* buffer ) const;
    private:
        const T data;
    };

template<>
void formater< std::string >::format( char* buffer ) const
    {
    strcpy( buffer, data.c_str());
    }

template<>
void formater< int >::format( char* buffer ) const
    {
    sprintf( buffer, "%d", data );
    }

template<>
void formater< const char* >::format( char* buffer ) const
    {
    strcpy( buffer, data );
    }

void generic_format( const char* format, const formater_base& f1 )
    {
    char buffer[ 1024 ];
    char* dst = buffer;
    for( const char* pos = format;
         *pos != '\0';
         ++pos )
        {
        if( *pos == '%' )
            {
            ++pos;
            if( *pos == '1' )
                {
                char tmp[ 1024 ];
                f1.format( tmp );
                strcpy( dst, tmp );
                dst += strlen( tmp );
                }
            else if( *pos == '%' )
                *dst++ = '%';
            else
                abort();
            }
        else
            *dst++ = *pos;
        }
    *dst = '\0';
    printf( "%s", buffer );
    }

void generic_format( const char* format, const formater_base& f1, const formater_base& f2 )
    {
    char buffer[ 1024 ];
    char* dst = buffer;
    for( const char* pos = format;
         *pos != '\0';
         ++pos )
        {
        if( *pos == '%' )
            {
            ++pos;
            if( *pos == '1' )
                {
                char tmp[ 1024 ];
                f1.format( tmp );
                strcpy( dst, tmp );
                dst += strlen( tmp );
                }
            else if( *pos == '2' )
                {
                char tmp[ 1024 ];
                f2.format( tmp );
                strcpy( dst, tmp );
                dst += strlen( tmp );
                }
            else if( *pos == '%' )
                *dst++ = '%';
            else
                abort();
            }
        else
            *dst++ = *pos;
        }
    *dst = '\0';
    printf( "%s", buffer );
    }

template< typename T1 >
void stringomatic( const char* format, T1 arg1 )
    {
    generic_format( format, formater< T1 >( arg1 ));
    }

template< typename T1, typename T2 >
void stringomatic( const char* format, T1 arg1, T2 arg2 )
    {
    generic_format( format, formater< T1 >( arg1 ), formater< T2 >( arg2 ));
    }

void test()
    {
    std::string foo( "foo" );
    int i = 1;
    stringomatic( "%1\n", foo );
    stringomatic( "%1\n", i );
    }

void foo1( const char* p, int b )
    {
    stringomatic( "P is %1 and b is %2\n", p, b );
    }

void foo2( const char* p, int b )
    {
    printf( "P is %s and b is %d\n", p, b );
    }

int main()
    {
//    test();
    foo1( "p", 1 );
    foo2( "p", 1 );
    }

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.