Results 1 to 6 of 6

Thread: va_start used in function with fixed args

  1. #1
    Join Date
    Sep 2006
    Posts
    27
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default va_start used in function with fixed args

    Hi,

    I'm not too keen on variable argument lists, but I'd like to use them for some logging functions.
    Suppose the prototype for logging functions is

    void Log( const String& sMessage, const int iLevel, const bool bUseLineEnd );

    String already takes variable argument lists in it's sPrintf function, which also returns a reference to this, so I could use

    Log( String().sPrintf( "test %d", 5 ), level, true ); for example.

    That's not really a problem, but what happens: String is constructed, then allocates memory, then calls sprintf and returns a reference to itself. Internally, Log copies the memory from String into pre-allocated space. The call returns, and String and it's memory are deallocated.
    What I would rather like to see, is that the sprintf call happens directly on the pre-allocated memory in Log. That saves allocating, memcpy and deallocation. However, I would also like to keep the same prototype, so that I can use Log( "test %d", 5, level, true );

    Variable arguments can't be listed first, so my first thought was to simply declare all possible functions:

    template< class T0 >
    void Log( const char* Format, const T0 arg0, const int iLevel, const bool bLineEnd );
    template< class T0, class T1 >
    void Log( const char* Format, const T0 arg0, const T1 arg1, const int iLevel, const bool bLineEnd );

    and so on.
    Implementating this was easy at first sight: let the Logger class have a method that accepts a va_list and construct the list from the arguments.
    template< class T0 >
    void Log( const char* Format, const T0 arg0, const int iLevel, const bool bLineEnd )
    {
    va_list args;
    va_start( args, Format );
    InternalLogFunction( Format, args, iLevel, bLineEnd );
    va_end( args );
    }

    This does excatly what I want, though it's not overly pretty, but gcc (4.1.2) chokes on this saying "va_start used in function with fixed args".
    I don't really understand why it is not allowed (afaik va_start just lets args point to the next element on the stack, arg0 in this case), can someone explain this?
    Also, what would be other ways to achieve this? What I basically want is a variable argument list of some kind, followed by 2 named parameters. (ok I could just use Log( const int, const bool, const char*, ... ) but it would just make writing much easier if it behaved like the non-printf Log)

    Thanks!

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: va_start used in function with fixed args

    Why do you need va_start in that function?

  3. #3
    Join Date
    Sep 2006
    Posts
    27
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: va_start used in function with fixed args

    Quote Originally Posted by jacek View Post
    Why do you need va_start in that function?
    I'm using void InternalLogFunction( char* Format, va_list& Args, const int, const bool ); so i need va_start to initialize the va_list.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: va_start used in function with fixed args

    Quote Originally Posted by stinos View Post
    I'm using void InternalLogFunction( char* Format, va_list& Args, const int, const bool ); so i need va_start to initialize the va_list.
    Indeed, I missed that.

    The problem is that the standard doesn't say anything about using va_list in a function with fixed number of parameters, so compilers might behave differently. The parameter you pass to va_start() is defined as the rightmost one and if you follow the standard strictly this makes va_start() useless in your case.

    The easiest solution would be to move those last two parameters to the front, but I assume you can't do that, so instead you could change your InternalLogFunction() to something similar to qDebug() stream:
    Qt Code:
    1. void Log( const char* Format, const T0 arg0, const int iLevel, const bool bLineEnd )
    2. {
    3. InternalLogStream( iLevel, bLineEnd, Format ) << arg0;
    4. }
    To copy to clipboard, switch view to plain text mode 
    or something like that.

  5. #5
    Join Date
    Sep 2006
    Posts
    27
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: va_start used in function with fixed args

    Quote Originally Posted by jacek View Post
    The easiest solution would be to move those last two parameters to the front, but I assume you can't do that, so instead you could change your InternalLogFunction() to something similar to qDebug() stream:
    didn't think about that. Wouldn't it require partly reinventing the printf mechanism?

    Suppose a case with 3 parameters:
    Log( "%d %s %d", 3, "test", 3, level, true );
    that would use
    InternalLogStream( iLevel, bLineEnd, Format ) << arg0 << arg1 << arg2;
    Each call to << should move on to the next '%' found in the format string, convert the argument, append result to internal string. That's what printf does..


    edit after thinking it through: it's really not a bad idea at all. It would require a call to 'Flush' or so after the InternalLogStream() calls because it has no way of knowing which argument is the last one, but I like the fact it uses templates: there's no way you can write a call with an argument that doesn't support conversion as the compiler would spot it immedeately so it's safer than normal printf. It might be somewhat slower though, still have to figure that out.
    Last edited by stinos; 27th November 2008 at 08:13.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: va_start used in function with fixed args

    Quote Originally Posted by stinos View Post
    Wouldn't it require partly reinventing the printf mechanism?
    Yes, but you can't use printf() because of those last two parameters.

Similar Threads

  1. QPSQL problem
    By LoneWolf in forum Installation and Deployment
    Replies: 60
    Last Post: 4th November 2009, 14:22
  2. QPSQL driver in windows
    By brevleq in forum Installation and Deployment
    Replies: 31
    Last Post: 14th December 2007, 12:57
  3. how to add static library into qmake
    By Namrata in forum Qt Tools
    Replies: 1
    Last Post: 20th November 2007, 17:33
  4. KDE/QWT doubt on debian sarge
    By hildebrand in forum KDE Forum
    Replies: 13
    Last Post: 25th April 2007, 06:13
  5. use qpsql
    By raphaelf in forum Installation and Deployment
    Replies: 34
    Last Post: 22nd August 2006, 12:52

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.