Boost logo

Boost :

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.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk