Boost logo

Boost :

From: Tom Becker (voidampersand_at_[hidden])
Date: 2001-12-24 15:41:40


On Mon, 24 Dec 2001 02:44:38 +0800, joel de guzman wrote:
>----- Original Message -----
>From: "Keith Burton" :
> > Sorry I was unclear
>>
>> most long expressions contain many ()s but not many contain %
>> therefore it is easier to see what is each parameter
>
>No one ever wins this battle over syntax. It's always very subjective.
>My favorite color is blue, hers is red, which is better and which
>should we choose for our new car? A compromise? violet?
>akkk, I don't think so :-)

How about if it supports printf syntax? Anything that departs from
printf syntax is likely to be perceived as a compromise, unless it's
clearly better. But the main problem with printf is its lack of type
safety. I think people are pretty comfortable with the syntax. So if
we could keep the familiar syntax and use C++ to provide type safety,
people might like it.

     cout << format("%d, %f", x, y) << endl;

Here's a really quick and dirty example I threw together to show what
I'm thinking. The formatting code in 'tostream' is just a dummy to
show that it has access to all the arguments by index. A real
formatter should actually use the format string. There are some
obvious optimizations, and I'm sure there's plenty of places where it
could be better, but the main thing is I wanted to get something out
where people could comment on it.

Regards,

   Tom

#include <iostream>
#include <string>
#include <vector>

using std::ostream;
using std::string;
using std::cout;
using std::endl;
using std::vector;

struct formatter
{
     formatter(const char* f) :
         f_(f)
     {
     }

     void tostream(ostream& out) const
     {
         out << f_;
         int n = arg_ptrs_.size();
         for (int i = 0; i < n; ++i)
         {
             out << " ";
             arg_getters_[i](arg_ptrs_[i], out);
         }
     }

     typedef void (*arg_getter)(void* arg_ptr, ostream& out);
    
     template<typename T>
     static void get_arg(void* arg_ptr, ostream& out)
     {
         out << *reinterpret_cast<T*>(arg_ptr);
     }

     vector<void*> arg_ptrs_;
     vector<arg_getter> arg_getters_;
     const char* f_;
};

inline ostream& operator<<(ostream& out, const formatter& f)
{
     f.tostream(out);
     return out;
}

template<typename T1>
struct formatter1 : public formatter
{
     formatter1(const char* f, T1 a1) :
         formatter(f)
     {
         arg_ptrs_.push_back(&a1);
         arg_getters_.push_back(&get_arg<T1>);
     }
};

template<typename T1, typename T2>
struct formatter2 : public formatter1<T1>
{
     formatter2(const char* f, T1 a1, T2 a2) :
         formatter1(f, a1)
     {
         arg_ptrs_.push_back(&a2);
         arg_getters_.push_back(&get_arg<T2>);
     }
};

inline formatter format(const char* f)
{
     return formatter(f);
}

template<typename T1>
inline formatter1<T1> format(const char* f, T1 a1)
{
     return formatter1<T1>(f, a1);
}

template<typename T1, typename T2>
inline formatter2<T1, T2> format(const char* f, T1 a1, T2 a2)
{
     return formatter2<T1, T2>(f, a1, a2);
}

int main()
{
     short x = 2;
     float y = 3.14;
     cout << format("%d, %f", x, y) << endl;
    
     return 0;
}

-- 
--
Tom Becker                      "Within C++, there is a much smaller and
<voidampersand_at_[hidden]>        cleaner language struggling to get out."
                                                      -- Bjarne Stroustrup

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