From: Sven Van Echelpoel (sven.vanechelpoel.sv_at_[hidden])
Date: 2002-05-15 07:24:48


Hi y'all,

I missed the original discussion on the operator%-vs-arg() issue, but
after reading Samuel's last mail I got an idea. A syntax like the one
below is a little bit more expressive that simply format() % ... % ...

formatter fmt;

fmt.format( "Enter a number between %p1 and %p2" )
        %p1( 10 )
        %p2( 100 );

Don't you think. Here's how I achieved it (on the top of my head):

#include <sstream>
#include <string>
#include <iostream>

using namespace std;

class format_param;

class formatter
{
public:

 formatter& operator % ( format_param const& );

 formatter& format( char const* fmt )
 {
  mResult = fmt;
  return ( *this );
 }

 string const& str()
 {
  return ( mResult );
 }

private:
 string mResult;
};

class format_param
{
public:

 void replace( std::string& s ) const
 {
  string::size_type sidx = s.find( param_id );

  if ( string::npos != sidx )
  {
   string tmp = s.substr( 0, sidx );
   tmp += oss.str();

   if ( sidx + param_id.length() < s.length() )
   {
    tmp += s.substr( sidx + param_id.length() );
   }

   s = tmp;
  }
 }

protected:

 format_param( char const* id ) :
  param_id( id )
 {
 }

 template<typename T>
 void preformat( T const& t )
 {
  oss << t;
 }

private:
 string param_id;
 ostringstream oss;
};

class p1 : public format_param
{
public:
 template<typename T>
 p1( T const& t ) :
  format_param( "%p1" )
 {
  preformat( t );
 }
};

class p2 : public format_param
{
public:
 template<typename T>
 p2( T const& t ) :
  format_param( "%p2" )
 {
  preformat( t );
 }
};

// more of these classes p3...pN

formatter& formatter::operator%( format_param const& param )
{
 param.replace( mResult );
 return ( *this );
}

int main(int argc, char* argv[])
{
 formatter fmt;

 fmt.format( "Enter a number between %p1 and %p2" )
        %p1( 10 )
        %p2( 100 );

 cout << fmt.str() << endl;
        
 return 0;
}

Of course, using this technique you wouldn't be able to specify
additional formatting options, but I have some ideas on that front as
well, although I don't yet know if they can be implemented. One syntax
looks a bit like this (haven't tried any code yet, so it might as well
prove to be impossible, but by showing it, it might spawn other
alternatives):

format( "%p1" ) %p1( 10 ) [Hex][Width=10];

I will think on it some more. An even nicer syntax would be:

format( "%p1" )
        p1 = 10 [Hex][Width=10];

or something similar, but I know I might be stretching things a wee bit
(I'm not a standardite :) ). One idea is to let p1 be a global of a type
whose assignment operator returns something that can be inserted into
the expression (equally in [Width=10]). I'll ponder on it some more
while you chew this one.

Svenne.

-- 
If you can remain calm while all others around you are losing their
heads, maybe you just don't understand the problem.