From -7150962233806673562
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,782fb3724018b13e
X-Google-Attributes: gidf78e5,public
X-Google-ArrivalTime: 2001-05-19 22:32:02 PST
Path: archiver1.google.com!newsfeed.google.com!newsfeed.stanford.edu!news.tele.dk!212.74.64.35!colt.net!dispose.news.demon.net!news.demon.co.uk!demon!mail2news.demon.co.uk!not-for-mail
From: "Paul Mensonides" <pmenso57@home.com>
Newsgroups: comp.std.c++
Subject: Re: All I want for Christmas (was C++0x)
Date: Sun, 20 May 2001 05:31:20 GMT
Organization: Excite@Home - The Leader in Broadband http://home.com/faster
Approved: Fergus Henderson <fjh@cs.mu.oz.au>, moderator of comp.std.c++
Message-ID: <q7DN6.31192$p33.601247@news1.sttls1.wa.home.com>
References: <089101c0e06e$e2494190$1200a8c0@abeast1.com>
X-Trace: mail2news.demon.co.uk 990336686 mail2news:8557 mail2news mail2news.demon.co.uk
X-Complaints-To: abuse@demon.net
X-Mail2News-Path: news.demon.net!mulga.cs.mu.oz.au
X-Authentication-Warning: mulga.cs.mu.OZ.AU: fjh set sender to devnull@stump.algebra.com using -f
X-Robomod: STUMP, ichudov@algebra.com (Igor Chudov)
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 5.50.4133.2400
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
NNTP-Posting-Date: Sat, 19 May 2001 16:14:30 PDT
Lines: 179
Xref: archiver1.google.com comp.std.c++:5006


"David Abrahams" <abrahams@mediaone.net> wrote in message
news:089101c0e06e$e2494190$1200a8c0@abeast1.com...
|
| "Paul Mensonides" <pmenso57@home.com> wrote in message
| news:153N6.24719$p33.428418@news1.sttls1.wa.home.com...
| > Hey, Andrei, what do you think of some type of templated parameter list?
| For
| > example...
| >
| > template<class T> class SomeCollection {
| >     private:
| >         unsigned m_size;
| >         T* m_v;
| >     public:
| >         template<class U, V(...)> void for_each(U (T::* pm)(V), V) {
| >             for (int i = 0; i < m_size; ++i) {
| >                 m_v[i].*pm(#V); // #V indicates values rather than type
| >             }
| >         }
| > };
|
| Something like this is on my big-10 list of missing template features. It is
| a sad fact of C++ programming that many idioms require the writing of
| forwarding functions. Doing this with templates can get really frustrating
| when they need overloads to deal with all the different combinations.
| Usually, I have to resort to C++ code generation (using, e.g., Python) just
| to ensure I don't make any mistakes. I rather like your syntax, too, though
| it should be possible to lose the pound sign (why not just declare v of type
| V?) and the parens around the ellipsis (they seem to indicate a function).
|
| -Dave

The only reason is that I didn't use something like V v, is because "V" is not a
type, it is a list of types.  I was just trying to make it clear that this
function takes a variable number of parameters (statically, of course, i.e. not
....) and directly forwards them in a non-named way.  Which is why I used a
"for_each" type thing.  You could directly refer to arguments inside the
template with pound signs (i.e. V(#1)) or something.  Of course, you would have
to instantiate the template with at least that many arguments, but then you
could change the template definition:

template<class U, V(2)> void for_each(U (T::* pm)(V), V); // V(2) means: AT
LEAST 2 arguments

class X {
public:
    void f(int, int);
};

//for a call:

void g() {
    int x = 0;
    float y = 2.0f;
    SomeCollection<X> z;
        // populate z...
    z.for_each(&X::f(int, float), x, y);
}

//
    inside "for_each," each type in "V" can be explicitly referred to by V[0]
and each value passed to "for_each" can be referred to by #V[0] (or #V[1],
etc.).  That is the reason I used the pound sign, to differentiate between
values passed versus their types.  In the "for_each" case, I passed the values
on to some other function directly.  If I wanted to access these values directly
I would use the de-typer operator :):

template<class RETTYPE, PARAMLIST(2)> void for_each(RETTYPE (T::*
pM)(PARAMLIST), PARAMLIST) {
    // verify arguments:

    if (#PARAMLIST[0] < PARAMLIST[0]()) throw int();
    if (#PARAMLIST[1] < PARAMLIST[1]()) throw int();
    //  ^--value----^   ^--type----^ ^--ctor call

    // never mind what this "comparison" is supposed to do, just illustrating
this syntax

    for (unsigned i = 0; i < m_size; ++i) {
        (m_v[i].*pM)(#V);
    }
}

for the call in g() above, this would expand too:

void SomeCollection<X>::for_each(void (X::* pM)(int, float), int arg1, float
arg2) {
    if (arg1 < int()) throw int();
    if (arg2 < float()) throw int();
    for (unsigned i = 0; i < m_size, ++i) {
        (m_v[i].*pM)(arg1, arg2);
    }
}

where:
    RETYPE = void (can only be used where "type" void can be, or compile time
error)
    V[0] = int
    V[1] = float
    #V[0] = unnamedArg1 (arg1, in this example)
    #V[1] = unnamedArg2 (arg2)
    #V = (unnamedArg1, unnamedArg2)
        (i.e. functionClosure(arg1, arg2) not sequencing: functionClosure((arg1,
arg2))
    T = "class" X

(To Andrei):
    I'm not saying this particular "syntax" is the good, just that it seemed
fairly clean, off the top of my head.  This is nothing like the varargs
mechanism, as different copies would be instantiated with different parameters
(and numbers of parameters), likewise, this would be thoroughly typesafe and
would mesh fine with the rest of C++.  This type of mechanism would be to
explicitly reduce the over- (mis-) use of the recursive templates, not to
mention overloading template functions with variable number of arguments, i.e.

template<class A> void f(A a);
template<class A, class B> void f(A a, B b);
template<class A, class B, class C> void f(A a, B b, C c);
    // etc.

speaking of typelists (ala Loki), this type of thing could ITERATE typelist
definitions rather than having #define TYPELIST_XX(type, _VAR_ARGS_)
TypeList<type, TYPELIST_XW(_VAR_ARGS_)> over and over or
    TypeList<int, TypeList<float, NullType> > ... etc. etc.

I agree that recursive templates are extremely interesting and powerful, as you
have shown in your book.  But for something as oft used as "for_each" like
stuff, this should be directly part of the language.

Along these same lines, C++ should (as part of the template mechanism) have
support for iterating code generation so that stuff like GenScatterHierarchy and
GenLinearHierarchy (which *rely* on good optimization).

Say like (and once again, never mind this specific syntax):

template<V(...)> class AbstractVisitor {
    public:
        #for_each X in V { // never mind this evil VB-type syntax too :)
            virtual void Visit(const V[X]&) { return; }
        }
};

then you could have:

template<V(...)> ConcreteVisitor : public AbstractVisitor<V> {
public: // handle images and paragraphs only.
    void Visit(const Image& img) {
        // handle images
    }
    void Visit(const Paragraphs& para) {
        // handle paragraphs
    }
};

This type of thing extends to your compile-time "if" that you mentioned
earlier..

template<bool T> void f() {
    #if (T) {
        // do something
    }
    #else {
        // do something else
    }
}

Once again, I'm referring to an idea (not a specific syntax), and I may be
poorly expressing myself. :(

Paul Mensonides


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]



