On Wednesday 23 of November 2011, Lubos Lunak wrote:
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.
Oh well, I guess I couldn't resist the temptation to try at least a proof of
concept. The attached testapp (depending on #define OPT) compiles things like
string1 + "foo" + string2 + "bar" + string3 into a call to a single function
which allocates just a single string object for the result of the operation,
no intermediate string objects or allocations are required.
So it indeed looks doable and we can have efficient and at the same time not
ackward to use string operations. Something for the next Hackweek or so.
Could somebody try that it works with the Windows compiler as well?
--
Lubos Lunak
l.lunak@suse.cz
#include <stdio.h>
#include <string.h>
class string
{
public:
string( const char* str = NULL );
string( const string& );
string( char* data, int len );
string& operator=( const string& );
string& operator+=( const string& );
~string();
const char* str() const;
// private:
int len;
char* data;
};
#define OPT
inline string::string( char* data, int len )
: len( len )
, data( data )
{
}
#ifndef OPT
inline string operator+( const string& str1, const string& str2 )
{
return string( str1 ) += str2;
}
#else
template< typename T1, typename T2 >
class stringplus
{
public:
stringplus( const T1& s1, const T2& s2 );
operator string() const;
// private:
const T1& str1;
const T2& str2;
};
template< typename T1, typename T2 >
inline stringplus< T1, T2 >::stringplus( const T1& s1, const T2& s2 )
: str1( s1 )
, str2( s2 )
{
}
template< typename T1, typename T2 >
inline stringplus< T1, T2 > operator+( const T1& str1, const T2& str2 )
{
return stringplus< T1, T2 >( str1, str2 );
}
template< typename T >
static int len( const T& s );
template< typename T >
static void copydata( char* dest, const T& s );
inline int len( const char* s )
{
return strlen( s );
}
inline void copydata( char* dest, const char* s )
{
strcpy( dest, s );
}
template<>
inline int len( const string& s )
{
return s.len;
}
template<>
inline void copydata( char* dest, const string& s )
{
strcpy( dest, s.data );
}
template< typename T1, typename T2 >
inline int len( const stringplus< T1, T2 >& str )
{
return len( str.str1 ) + len( str.str2 );
}
template< typename T1, typename T2 >
inline void copydata( char* dest, const stringplus< T1, T2 >& str )
{
int len1 = len( str.str1 );
copydata( dest, str.str1 );
copydata( dest + len1, str.str2 );
}
template< typename T1, typename T2 >
string concat( const T1& str1, const T2& str2 )
{
int len1 = len( str1 );
int len2 = len( str2 );
char* newdata = new char[ len1 + len2 + 1 ];
copydata( newdata, str1 );
copydata( newdata + len1, str2 );
printf( "ALLOC %s\n", newdata );
return string( newdata, len1 + len2 );
}
template< typename T1, typename T2 >
inline string make_concat( const stringplus< T1, T2 >& str )
{
return concat( str.str1, str.str2 );
}
// A helper function is needed, because the compiler does not like
// a template that recursively refers to itself, i.e. this:
// template< typename T1, typename T2, typename T3 >
// inline stringplus< stringplus< T1, T2 >, T3 >::operator string() const .
// Not sure whether maybe I'm doing something wrong, but this easily solves it.
template< typename T1, typename T2, typename T3 >
inline string make_concat( const stringplus< T1, T2 >& str1, const T2& str2 )
{
return concat( str1.str1, str1.str2, str2 );
}
template< typename T1, typename T2 >
inline stringplus< T1, T2 >::operator string() const
{
return make_concat( *this );
}
#endif
inline const char* string::str() const
{
return data;
}
string::string( const char* str )
: len( str != NULL ? strlen( str ) : 0 )
, data( new char[ len + 1 ] )
{
if( str != NULL )
strcpy( data, str );
else
*data = '\0';
printf( "ALLOC %s\n", data );
}
string::string( const string& str )
: len( str.len )
, data( new char[ len + 1 ] )
{
strcpy( data, str.data );
printf( "ALLOC %s\n", data );
}
string& string::operator=( const string& str )
{
if( data == str.data )
return *this;
delete[] data;
data = new char[ str.len + 1 ];
strcpy( data, str.data );
len = str.len;
printf( "ALLOC %s\n", data );
return *this;
}
string& string::operator+=( const string& str )
{
char* newdata = new char[ len + str.len + 1 ];
strcpy( newdata, data );
strcat( newdata, str.data );
delete[] data;
data = newdata;
len += str.len;
printf( "ALLOC %s\n", data );
return *this;
}
string::~string()
{
delete[] data;
}
string test2( const string& s1, const string& s2 )
{
return s1 + "-" + s2 + "-" + s1;
}
void test()
{
string s1( "test" );
string s2( "this" );
string s3 = test2( s1, s2 );
printf( "%s\n", s3.str());
}
int main()
{
test();
}
Context
- Re: [Libreoffice] message construction bloat ... (continued)
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.